├── yuv ├── consumer-rules.pro ├── src │ └── main │ │ ├── cpp │ │ ├── lib │ │ │ ├── x86 │ │ │ │ └── libyuv.so │ │ │ ├── x86_64 │ │ │ │ └── libyuv.so │ │ │ ├── arm64-v8a │ │ │ │ └── libyuv.so │ │ │ └── armeabi-v7a │ │ │ │ └── libyuv.so │ │ ├── utils │ │ │ └── logger.h │ │ ├── include │ │ │ ├── libyuv │ │ │ │ ├── version.h │ │ │ │ ├── rotate_argb.h │ │ │ │ ├── basic_types.h │ │ │ │ ├── scale_argb.h │ │ │ │ ├── compare.h │ │ │ │ ├── cpu_id.h │ │ │ │ ├── convert_from.h │ │ │ │ ├── compare_row.h │ │ │ │ ├── rotate.h │ │ │ │ ├── scale.h │ │ │ │ ├── mjpeg_decoder.h │ │ │ │ ├── video_common.h │ │ │ │ ├── rotate_row.h │ │ │ │ ├── convert_from_argb.h │ │ │ │ ├── macros_msa.h │ │ │ │ └── convert.h │ │ │ └── libyuv.h │ │ ├── CMakeLists.txt │ │ └── easyyuv.cpp │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── theeasiestway │ │ └── yuv │ │ ├── entities │ │ ├── ArgbFrame.kt │ │ └── YuvFrame.kt │ │ ├── Constants.kt │ │ ├── FramesFactory.kt │ │ └── YuvUtils.kt ├── .gitignore ├── proguard-rules.pro └── build.gradle ├── yuv.aar ├── settings.gradle ├── app ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── drawable │ │ │ ├── ic_camera_rear_24dp.xml │ │ │ ├── ic_camera_front_24dp.xml │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ └── layout │ │ │ └── activity_main.xml │ │ ├── java │ │ └── com │ │ │ └── theeasiestway │ │ │ └── libyuvwrapper │ │ │ ├── App.kt │ │ │ ├── ControllerVideo.kt │ │ │ └── MainActivity.kt │ │ └── AndroidManifest.xml ├── .gitignore ├── proguard-rules.pro └── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── .idea ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── misc.xml ├── runConfigurations.xml └── gradle.xml ├── gradle.properties ├── gradlew.bat ├── README.md └── gradlew /yuv/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /yuv.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/yuv.aar -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name='LibyuvWrapper' 2 | include ':app' 3 | include ':yuv' 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | EasyYUV 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /yuv/src/main/cpp/lib/x86/libyuv.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/yuv/src/main/cpp/lib/x86/libyuv.so -------------------------------------------------------------------------------- /yuv/src/main/cpp/lib/x86_64/libyuv.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/yuv/src/main/cpp/lib/x86_64/libyuv.so -------------------------------------------------------------------------------- /yuv/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /yuv/src/main/cpp/lib/arm64-v8a/libyuv.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/yuv/src/main/cpp/lib/arm64-v8a/libyuv.so -------------------------------------------------------------------------------- /yuv/src/main/cpp/lib/armeabi-v7a/libyuv.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/yuv/src/main/cpp/lib/armeabi-v7a/libyuv.so -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | *.cxx 9 | app/.cxx/* 10 | .externalNativeBuild -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | *.cxx 9 | app/.cxx/* 10 | .externalNativeBuild -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /yuv/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | *.cxx 9 | app/.cxx/* 10 | .externalNativeBuild -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theeasiestway/android-yuv-utils/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jun 22 14:56:56 KRAT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/theeasiestway/libyuvwrapper/App.kt: -------------------------------------------------------------------------------- 1 | package com.theeasiestway.libyuvwrapper 2 | 3 | import android.app.Application 4 | import androidx.camera.camera2.Camera2Config 5 | import androidx.camera.core.CameraXConfig 6 | 7 | class App: Application(), CameraXConfig.Provider { 8 | 9 | override fun getCameraXConfig(): CameraXConfig { 10 | return Camera2Config.defaultConfig() 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_camera_rear_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /yuv/src/main/cpp/utils/logger.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Loboda Alexey on 27.03.2020. 3 | // 4 | 5 | #ifndef ANDROIDCODECPACK_LOGGER_H 6 | #define ANDROIDCODECPACK_LOGGER_H 7 | #include 8 | 9 | 10 | #define LOGE(tag, ...) __android_log_print(ANDROID_LOG_ERROR, tag, __VA_ARGS__) 11 | #define LOGW(tag, ...) __android_log_print(ANDROID_LOG_WARN, tag, __VA_ARGS__) 12 | #define LOGI(tag, ...) __android_log_print(ANDROID_LOG_INFO, tag, __VA_ARGS__) 13 | #define LOGD(tag, ...) __android_log_print(ANDROID_LOG_DEBUG, tag, __VA_ARGS__) 14 | 15 | #endif //ANDROIDCODECPACK_LOGGER_H 16 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_camera_front_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /yuv/src/main/cpp/include/libyuv/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_VERSION_H_ 12 | #define INCLUDE_LIBYUV_VERSION_H_ 13 | 14 | #define LIBYUV_VERSION 1759 15 | 16 | #endif // INCLUDE_LIBYUV_VERSION_H_ 17 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /yuv/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /yuv/src/main/java/com/theeasiestway/yuv/entities/ArgbFrame.kt: -------------------------------------------------------------------------------- 1 | package com.theeasiestway.yuv.entities 2 | 3 | import java.nio.ByteBuffer 4 | 5 | // 6 | // Created by Loboda Alexey on 25.06.2020. 7 | // 8 | 9 | class ArgbFrame { 10 | 11 | lateinit var data: ByteBuffer; private set 12 | var dataStride: Int = 0; private set 13 | 14 | var width: Int = 0; private set 15 | var height: Int = 0; private set 16 | 17 | fun fill(data: ByteBuffer, dataStride: Int, width: Int, height: Int) { 18 | this.data = data 19 | this.dataStride = dataStride 20 | this.width = width 21 | this.height = height 22 | } 23 | 24 | fun asArray(): ByteArray { 25 | return ByteBuffer.allocate(data.capacity()).put(data).array() 26 | } 27 | 28 | fun free() { 29 | data = ByteBuffer.allocate(1) 30 | dataStride = 0 31 | width = 0 32 | height = 0 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /yuv/src/main/cpp/include/libyuv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_H_ 12 | #define INCLUDE_LIBYUV_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | #include "libyuv/compare.h" 16 | #include "libyuv/convert.h" 17 | #include "libyuv/convert_argb.h" 18 | #include "libyuv/convert_from.h" 19 | #include "libyuv/convert_from_argb.h" 20 | #include "libyuv/cpu_id.h" 21 | #include "libyuv/mjpeg_decoder.h" 22 | #include "libyuv/planar_functions.h" 23 | #include "libyuv/rotate.h" 24 | #include "libyuv/rotate_argb.h" 25 | #include "libyuv/row.h" 26 | #include "libyuv/scale.h" 27 | #include "libyuv/scale_argb.h" 28 | #include "libyuv/scale_row.h" 29 | #include "libyuv/version.h" 30 | #include "libyuv/video_common.h" 31 | 32 | #endif // INCLUDE_LIBYUV_H_ 33 | -------------------------------------------------------------------------------- /yuv/src/main/cpp/include/libyuv/rotate_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_ROTATE_ARGB_H_ 12 | #define INCLUDE_LIBYUV_ROTATE_ARGB_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | #include "libyuv/rotate.h" // For RotationMode. 16 | 17 | #ifdef __cplusplus 18 | namespace libyuv { 19 | extern "C" { 20 | #endif 21 | 22 | // Rotate ARGB frame 23 | LIBYUV_API 24 | int ARGBRotate(const uint8_t* src_argb, 25 | int src_stride_argb, 26 | uint8_t* dst_argb, 27 | int dst_stride_argb, 28 | int src_width, 29 | int src_height, 30 | enum RotationMode mode); 31 | 32 | #ifdef __cplusplus 33 | } // extern "C" 34 | } // namespace libyuv 35 | #endif 36 | 37 | #endif // INCLUDE_LIBYUV_ROTATE_ARGB_H_ 38 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | -------------------------------------------------------------------------------- /yuv/src/main/java/com/theeasiestway/yuv/Constants.kt: -------------------------------------------------------------------------------- 1 | package com.theeasiestway.yuv 2 | 3 | // 4 | // Created by Loboda Alexey on 22.06.2020. 5 | // 6 | 7 | object Constants { 8 | 9 | // 10 | // Scale 11 | // 12 | 13 | /** If filtering is FILTER_NONE, a simple nearest-neighbor algorithm is 14 | * used. This produces basic (blocky) quality at the fastest speed. 15 | * If filtering is FILTER_BILINEAR, interpolation is used to produce a better 16 | * quality image, at the expense of speed. 17 | * If filtering is FILTER_BOX, averaging is used to produce ever better 18 | * quality image, at further expense of speed. */ 19 | 20 | const val FILTER_NONE = 0 // Point sample; Fastest. 21 | const val FILTER_LINEAR = 1 // Filter horizontally only. 22 | const val FILTER_BILINEAR = 2 // Faster than box, but lower quality scaling down. 23 | const val FILTER_BOX = 3 // Highest quality. 24 | 25 | // 26 | // Rotate 27 | // 28 | 29 | const val ROTATE_0 = 0 // No rotation. 30 | const val ROTATE_90 = 90 // Rotate 90 degrees clockwise. 31 | const val ROTATE_180 = 180 // Rotate 180 degrees. 32 | const val ROTATE_270 = 270 // Rotate 270 degrees clockwise. 33 | 34 | } -------------------------------------------------------------------------------- /yuv/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 29 7 | buildToolsVersion "29.0.3" 8 | 9 | defaultConfig { 10 | minSdkVersion 21 11 | targetSdkVersion 29 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | consumerProguardFiles 'consumer-rules.pro' 16 | 17 | externalNativeBuild { 18 | cmake { 19 | cppFlags "" 20 | } 21 | } 22 | } 23 | 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 28 | } 29 | } 30 | 31 | externalNativeBuild { 32 | cmake { 33 | path "src/main/cpp/CMakeLists.txt" 34 | version "3.10.2" 35 | } 36 | } 37 | 38 | sourceSets.main { 39 | jniLibs.srcDir 'src/main/cpp/lib' 40 | } 41 | } 42 | 43 | dependencies { 44 | implementation fileTree(dir: 'libs', include: ['*.jar']) 45 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 46 | implementation 'androidx.appcompat:appcompat:1.1.0' 47 | implementation 'androidx.core:core-ktx:1.3.0' 48 | } 49 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 29 7 | buildToolsVersion "29.0.3" 8 | 9 | defaultConfig { 10 | applicationId "com.theeasiestway.libyuvwrapper" 11 | minSdkVersion 21 12 | targetSdkVersion 29 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | externalNativeBuild { 17 | ndk { 18 | abiFilters 'armeabi-v7a' , 'arm64-v8a', 'x86', 'x86_64' 19 | } 20 | } 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | } 35 | 36 | dependencies { 37 | implementation fileTree(dir: 'libs', include: ['*.jar']) 38 | implementation project (':yuv') 39 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 40 | implementation 'androidx.appcompat:appcompat:1.1.0' 41 | implementation 'androidx.core:core-ktx:1.3.0' 42 | implementation "androidx.camera:camera-camera2:1.0.0-beta05" 43 | implementation "androidx.camera:camera-view:1.0.0-alpha12" 44 | implementation "androidx.camera:camera-extensions:1.0.0-alpha12" 45 | implementation "androidx.camera:camera-lifecycle:1.0.0-beta05" 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /yuv/src/main/java/com/theeasiestway/yuv/FramesFactory.kt: -------------------------------------------------------------------------------- 1 | package com.theeasiestway.yuv 2 | 3 | import com.theeasiestway.yuv.entities.ArgbFrame 4 | import com.theeasiestway.yuv.entities.YuvFrame 5 | import java.nio.ByteBuffer 6 | 7 | // 8 | // Created by Loboda Alexey on 25.06.2020. 9 | // 10 | 11 | object FramesFactory { 12 | 13 | fun instanceYuv(dstWidth: Int, dstHeight: Int): YuvFrame { 14 | val yuvFrame = YuvFrame() 15 | val ySize = dstWidth * dstHeight 16 | val uvSize = dstWidth * dstHeight / 4 17 | val y = ByteBuffer.allocateDirect(ySize) 18 | val u = ByteBuffer.allocateDirect(uvSize) 19 | val v = ByteBuffer.allocateDirect(uvSize) 20 | val extra = if (dstWidth % 2 == 0) 0 else 1 21 | yuvFrame.fill(y, u, v, dstWidth, dstWidth / 2 + extra, dstWidth / 2 + extra, dstWidth, dstHeight) 22 | return yuvFrame 23 | } 24 | 25 | fun instanceYuv(width: Int, height: Int, rotationMode: Int): YuvFrame { 26 | val newFrame = YuvFrame() 27 | val outWidth = if (rotationMode == 90 || rotationMode == 270) height else width 28 | val outHeight = if (rotationMode == 90 || rotationMode == 270) width else height 29 | val ySize = outWidth * outHeight 30 | val uvSize = outWidth * outHeight / 4 31 | val y = ByteBuffer.allocateDirect(ySize) 32 | val u = ByteBuffer.allocateDirect(uvSize) 33 | val v = ByteBuffer.allocateDirect(uvSize) 34 | val extra = if (outWidth % 2 == 0) 0 else 1 35 | newFrame.fill(y, u, v, outWidth, outWidth / 2 + extra, outWidth / 2 + extra, outWidth, outHeight) 36 | return newFrame 37 | } 38 | 39 | fun instanceArgb(width: Int, height: Int): ArgbFrame { 40 | val newFrame = ArgbFrame() 41 | val data = ByteBuffer.allocateDirect((width * height) * 32) 42 | val extra = if (width % 2 == 0) 0 else 1 43 | val dataStride = width * 4 + extra 44 | newFrame.fill(data, dataStride, width, height) 45 | return newFrame 46 | } 47 | } -------------------------------------------------------------------------------- /yuv/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | 13 | add_library( # Sets the name of the library. 14 | easyyuv 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | easyyuv.cpp ) 21 | 22 | include_directories(${PROJECT_SOURCE_DIR}/include) 23 | 24 | #add other prebuilt libraries 25 | add_library(yuv SHARED IMPORTED) 26 | 27 | set_target_properties(yuv PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/lib/${ANDROID_ABI}/libyuv.so) 28 | 29 | # Searches for a specified prebuilt library and stores the path as a 30 | # variable. Because CMake includes system libraries in the search path by 31 | # default, you only need to specify the name of the public NDK library 32 | # you want to add. CMake verifies that the library exists before 33 | # completing its build. 34 | 35 | find_library( # Sets the name of the path variable. 36 | log-lib 37 | 38 | # Specifies the name of the NDK library that 39 | # you want CMake to locate. 40 | log ) 41 | 42 | # Specifies libraries CMake should link to your target library. You 43 | # can link multiple libraries, such as libraries you define in this 44 | # build script, prebuilt third-party libraries, or system libraries. 45 | 46 | target_link_libraries( # Specifies the target library. 47 | easyyuv 48 | yuv 49 | # Links the target library to the log library 50 | # included in the NDK. 51 | ${log-lib} ) -------------------------------------------------------------------------------- /yuv/src/main/cpp/include/libyuv/basic_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_BASIC_TYPES_H_ 12 | #define INCLUDE_LIBYUV_BASIC_TYPES_H_ 13 | 14 | #include // For size_t and NULL 15 | 16 | #if !defined(INT_TYPES_DEFINED) && !defined(GG_LONGLONG) 17 | #define INT_TYPES_DEFINED 18 | 19 | #if defined(_MSC_VER) && (_MSC_VER < 1600) 20 | #include // for uintptr_t on x86 21 | typedef unsigned __int64 uint64_t; 22 | typedef __int64 int64_t; 23 | typedef unsigned int uint32_t; 24 | typedef int int32_t; 25 | typedef unsigned short uint16_t; 26 | typedef short int16_t; 27 | typedef unsigned char uint8_t; 28 | typedef signed char int8_t; 29 | #else 30 | #include // for uintptr_t and C99 types 31 | #endif // defined(_MSC_VER) && (_MSC_VER < 1600) 32 | // Types are deprecated. Enable this macro for legacy types. 33 | #ifdef LIBYUV_LEGACY_TYPES 34 | typedef uint64_t uint64; 35 | typedef int64_t int64; 36 | typedef uint32_t uint32; 37 | typedef int32_t int32; 38 | typedef uint16_t uint16; 39 | typedef int16_t int16; 40 | typedef uint8_t uint8; 41 | typedef int8_t int8; 42 | #endif // LIBYUV_LEGACY_TYPES 43 | #endif // INT_TYPES_DEFINED 44 | 45 | #if !defined(LIBYUV_API) 46 | #if defined(_WIN32) || defined(__CYGWIN__) 47 | #if defined(LIBYUV_BUILDING_SHARED_LIBRARY) 48 | #define LIBYUV_API __declspec(dllexport) 49 | #elif defined(LIBYUV_USING_SHARED_LIBRARY) 50 | #define LIBYUV_API __declspec(dllimport) 51 | #else 52 | #define LIBYUV_API 53 | #endif // LIBYUV_BUILDING_SHARED_LIBRARY 54 | #elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__APPLE__) && \ 55 | (defined(LIBYUV_BUILDING_SHARED_LIBRARY) || \ 56 | defined(LIBYUV_USING_SHARED_LIBRARY)) 57 | #define LIBYUV_API __attribute__((visibility("default"))) 58 | #else 59 | #define LIBYUV_API 60 | #endif // __GNUC__ 61 | #endif // LIBYUV_API 62 | 63 | // TODO(fbarchard): Remove bool macros. 64 | #define LIBYUV_BOOL int 65 | #define LIBYUV_FALSE 0 66 | #define LIBYUV_TRUE 1 67 | 68 | #endif // INCLUDE_LIBYUV_BASIC_TYPES_H_ 69 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /yuv/src/main/cpp/include/libyuv/scale_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_SCALE_ARGB_H_ 12 | #define INCLUDE_LIBYUV_SCALE_ARGB_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | #include "libyuv/scale.h" // For FilterMode 16 | 17 | #ifdef __cplusplus 18 | namespace libyuv { 19 | extern "C" { 20 | #endif 21 | 22 | LIBYUV_API 23 | int ARGBScale(const uint8_t* src_argb, 24 | int src_stride_argb, 25 | int src_width, 26 | int src_height, 27 | uint8_t* dst_argb, 28 | int dst_stride_argb, 29 | int dst_width, 30 | int dst_height, 31 | enum FilterMode filtering); 32 | 33 | // Clipped scale takes destination rectangle coordinates for clip values. 34 | LIBYUV_API 35 | int ARGBScaleClip(const uint8_t* src_argb, 36 | int src_stride_argb, 37 | int src_width, 38 | int src_height, 39 | uint8_t* dst_argb, 40 | int dst_stride_argb, 41 | int dst_width, 42 | int dst_height, 43 | int clip_x, 44 | int clip_y, 45 | int clip_width, 46 | int clip_height, 47 | enum FilterMode filtering); 48 | 49 | // Scale with YUV conversion to ARGB and clipping. 50 | LIBYUV_API 51 | int YUVToARGBScaleClip(const uint8_t* src_y, 52 | int src_stride_y, 53 | const uint8_t* src_u, 54 | int src_stride_u, 55 | const uint8_t* src_v, 56 | int src_stride_v, 57 | uint32_t src_fourcc, 58 | int src_width, 59 | int src_height, 60 | uint8_t* dst_argb, 61 | int dst_stride_argb, 62 | uint32_t dst_fourcc, 63 | int dst_width, 64 | int dst_height, 65 | int clip_x, 66 | int clip_y, 67 | int clip_width, 68 | int clip_height, 69 | enum FilterMode filtering); 70 | 71 | #ifdef __cplusplus 72 | } // extern "C" 73 | } // namespace libyuv 74 | #endif 75 | 76 | #endif // INCLUDE_LIBYUV_SCALE_ARGB_H_ 77 | -------------------------------------------------------------------------------- /yuv/src/main/java/com/theeasiestway/yuv/entities/YuvFrame.kt: -------------------------------------------------------------------------------- 1 | package com.theeasiestway.yuv.entities 2 | 3 | import android.media.Image 4 | import java.nio.ByteBuffer 5 | 6 | // 7 | // Created by Loboda Alexey on 22.06.2020. 8 | // 9 | 10 | class YuvFrame { 11 | 12 | lateinit var y: ByteBuffer; private set 13 | lateinit var u: ByteBuffer; private set 14 | lateinit var v: ByteBuffer; private set 15 | 16 | var yStride: Int = 0; private set 17 | var uStride: Int = 0; private set 18 | var vStride: Int = 0; private set 19 | 20 | var width: Int = 0; private set 21 | var height: Int = 0; private set 22 | 23 | fun fill(y: ByteBuffer, u: ByteBuffer, v: ByteBuffer, yStride: Int, uStride: Int, vStride: Int, width: Int, height: Int) { 24 | this.y = y 25 | this.u = u 26 | this.v = v 27 | this.yStride = yStride 28 | this.uStride = uStride 29 | this.vStride = vStride 30 | this.width = width 31 | this.height = height 32 | } 33 | 34 | fun fill(image: Image) { 35 | for (i in 0 until 3) { 36 | when(i) { 37 | 0 -> { 38 | y = image.planes[i].buffer 39 | yStride = image.planes[i].rowStride 40 | } 41 | 1 -> { 42 | u = image.planes[i].buffer 43 | uStride = image.planes[i].rowStride 44 | } 45 | 2 -> { 46 | v = image.planes[i].buffer 47 | vStride = image.planes[i].rowStride 48 | } 49 | } 50 | } 51 | width = image.width 52 | height = image.height 53 | } 54 | 55 | /** experimental method */ 56 | fun fill(width: Int, height: Int, data: ByteArray) { 57 | this.width = width 58 | this.height = height 59 | 60 | val yArr = ByteArray(width * height) 61 | val uArr = ByteArray(width * height / 4) 62 | val vArr = ByteArray(width * height / 4) 63 | 64 | System.arraycopy(data, 0, yArr, 0, yArr.size) 65 | System.arraycopy(data, yArr.size, uArr, 0, uArr.size) 66 | System.arraycopy(data, yArr.size + uArr.size, vArr, 0, uArr.size) 67 | 68 | y = ByteBuffer.allocateDirect(yArr.size).put(yArr) 69 | u = ByteBuffer.allocateDirect(uArr.size).put(uArr) 70 | v = ByteBuffer.allocateDirect(vArr.size).put(vArr) 71 | 72 | y.position(0) 73 | u.position(0) 74 | v.position(0) 75 | } 76 | 77 | fun asArray(): ByteArray { 78 | var array: ByteArray 79 | 80 | val yPos = y.position() 81 | val uPos = u.position() 82 | val vPos = v.position() 83 | 84 | try { 85 | array = ByteBuffer.allocate(y.capacity() + u.capacity() + v.capacity()).put(y).put(u).put(v).array() 86 | y.position(yPos) 87 | u.position(uPos) 88 | v.position(vPos) 89 | } catch (e: Exception) { 90 | 91 | array = ByteArray(size()) 92 | 93 | y.get(array, 0, y.remaining()) 94 | y.position(yPos) 95 | 96 | u.get(array, y.remaining(), u.remaining()) 97 | u.position(uPos) 98 | 99 | v.get(array, y.remaining() + u.remaining(), v.remaining()) 100 | v.position(vPos) 101 | } 102 | return array 103 | } 104 | 105 | fun size() = y.remaining() + u.remaining() + v.remaining() 106 | 107 | fun free() { 108 | y = ByteBuffer.allocate(1) 109 | u = ByteBuffer.allocate(1) 110 | v = ByteBuffer.allocate(1) 111 | yStride = 0 112 | uStride = 0 113 | vStride = 0 114 | width = 0 115 | height = 0 116 | } 117 | } -------------------------------------------------------------------------------- /yuv/src/main/cpp/include/libyuv/compare.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_COMPARE_H_ 12 | #define INCLUDE_LIBYUV_COMPARE_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Compute a hash for specified memory. Seed of 5381 recommended. 22 | LIBYUV_API 23 | uint32_t HashDjb2(const uint8_t* src, uint64_t count, uint32_t seed); 24 | 25 | // Hamming Distance 26 | LIBYUV_API 27 | uint64_t ComputeHammingDistance(const uint8_t* src_a, 28 | const uint8_t* src_b, 29 | int count); 30 | 31 | // Scan an opaque argb image and return fourcc based on alpha offset. 32 | // Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown. 33 | LIBYUV_API 34 | uint32_t ARGBDetect(const uint8_t* argb, 35 | int stride_argb, 36 | int width, 37 | int height); 38 | 39 | // Sum Square Error - used to compute Mean Square Error or PSNR. 40 | LIBYUV_API 41 | uint64_t ComputeSumSquareError(const uint8_t* src_a, 42 | const uint8_t* src_b, 43 | int count); 44 | 45 | LIBYUV_API 46 | uint64_t ComputeSumSquareErrorPlane(const uint8_t* src_a, 47 | int stride_a, 48 | const uint8_t* src_b, 49 | int stride_b, 50 | int width, 51 | int height); 52 | 53 | static const int kMaxPsnr = 128; 54 | 55 | LIBYUV_API 56 | double SumSquareErrorToPsnr(uint64_t sse, uint64_t count); 57 | 58 | LIBYUV_API 59 | double CalcFramePsnr(const uint8_t* src_a, 60 | int stride_a, 61 | const uint8_t* src_b, 62 | int stride_b, 63 | int width, 64 | int height); 65 | 66 | LIBYUV_API 67 | double I420Psnr(const uint8_t* src_y_a, 68 | int stride_y_a, 69 | const uint8_t* src_u_a, 70 | int stride_u_a, 71 | const uint8_t* src_v_a, 72 | int stride_v_a, 73 | const uint8_t* src_y_b, 74 | int stride_y_b, 75 | const uint8_t* src_u_b, 76 | int stride_u_b, 77 | const uint8_t* src_v_b, 78 | int stride_v_b, 79 | int width, 80 | int height); 81 | 82 | LIBYUV_API 83 | double CalcFrameSsim(const uint8_t* src_a, 84 | int stride_a, 85 | const uint8_t* src_b, 86 | int stride_b, 87 | int width, 88 | int height); 89 | 90 | LIBYUV_API 91 | double I420Ssim(const uint8_t* src_y_a, 92 | int stride_y_a, 93 | const uint8_t* src_u_a, 94 | int stride_u_a, 95 | const uint8_t* src_v_a, 96 | int stride_v_a, 97 | const uint8_t* src_y_b, 98 | int stride_y_b, 99 | const uint8_t* src_u_b, 100 | int stride_u_b, 101 | const uint8_t* src_v_b, 102 | int stride_v_b, 103 | int width, 104 | int height); 105 | 106 | #ifdef __cplusplus 107 | } // extern "C" 108 | } // namespace libyuv 109 | #endif 110 | 111 | #endif // INCLUDE_LIBYUV_COMPARE_H_ 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # android-yuv-utils 2 | CAUTION! The version from master branch actually works but has some issues like a lot of memory consumption and some other issues.. 3 | 4 | Compiled [libyuv](https://chromium.googlesource.com/libyuv/libyuv/) Google library and wrapper for it for easy and fast scale, rotate, mirror and convert frames from android Camera2 or CameraX. 5 | 6 | ## Supported features: 7 | 1. Horizontal and/or vertical scaling. 8 | 2. Rotating by 90, 180 or 270 degrees. 9 | 3. Mirror horizontally or vertically. 10 | 4. Convert android YUV_420_8888 frame to ARGB. 11 | 12 | ## Supported ABIs: 13 | armeabi-v7a, arm64-v8a, x86, x86_64 14 | 15 | ## How to use 16 | 17 | #### Init library: 18 | ```kotlin 19 | val yuvUtils = YuvUtils() // getting library instance 20 | ``` 21 | 22 | #### Prepare a frame from Camera2 or CameraX for scaling, rotating etc.: 23 | ```kotlin 24 | val image = ... // getting an image from Camera2 or CameraX api 25 | var yuvFrame = yuvUtils.convertToI420(image) // this step isn't mandatory but it may help you in case if the colors of the output frame (after scale, rotate etc.) are distorted 26 | ``` 27 | 28 | #### Scale: 29 | ```kotlin 30 | /* the first way */ 31 | val image = ... // getting an image from Camera2 or CameraX api 32 | val scaledWidth = image.width * 2 // getting current width and height 33 | val scaledHeight = image.height * 2 // of the image and for example double them 34 | yuvFrame = yuvUtils.scale(image, scaledWidth, scaledHeight, Constants.FILTER_BOX) 35 | 36 | /* the second way here yuvFrame was taken from the yuvUtils.convertToI420 method as showed above */ 37 | val scaledWidth = yuvFrame.width * 2 // getting current width and height 38 | val scaledHeight = yuvFrame.height * 2 // of the image and for example double them 39 | yuvFrame = yuvUtils.scale(yuvFrame, scaledWidth, scaledHeight, Constants.FILTER_BOX) 40 | ``` 41 | 42 | #### Rotate: 43 | ```kotlin 44 | val rotate = Constants.ROTATE_270 // setting the rotation angle 45 | yuvFrame = yuvUtils.rotate(image, rotate) 46 | /* or */ 47 | yuvFrame = yuvUtils.rotate(yuvFrame, rotate) 48 | ``` 49 | 50 | #### Mirror: 51 | ```kotlin 52 | /* for mirror horizontally */ 53 | yuvFrame = yuvUtils.mirrorH(image) 54 | /* or */ 55 | yuvFrame = yuvUtils.mirrorH(yuvFrame) 56 | 57 | /* for mirror vertically */ 58 | yuvFrame = yuvUtils.mirrorV(image) 59 | /* or */ 60 | yuvFrame = yuvUtils.mirrorV(yuvFrame) 61 | ``` 62 | 63 | #### Convert to ARGB: 64 | ```kotlin 65 | val argbFrame = yuvUtils.yuv420ToArgb(image) 66 | /* or */ 67 | val argbFrame = yuvUtils.yuv420ToArgb(yuvFrame) 68 | ``` 69 | 70 | ## Project structure 71 | #### The project consists of two modules: 72 | - **app** - here you can find a sample app that demonsrates scaling, rotating, mirroring and converting procedures by capturing frames from device's camera. 73 | - **yuv** - here you can find a C++ class that interacts with [libyuv 1759](https://chromium.googlesource.com/libyuv/libyuv/+/c5e45dcae58f5cb3eb893f8000c1de88a8fe3c4e) and JNI wrapper for interacting with it from Java/Kotlin layer. 74 | 75 | #### Compiled library: 76 | - **yuv.aar** - it's a compiled library of **yuv** module that mentioned above, it placed in a root directory of the project, you can easily add it to your project using gradle dependencies. First you have to place **yuv.aar** in the libs folder of your project and then add to your build.gradle the following: 77 | ````groovy 78 | dependencies { 79 | implementation fileTree(dir: 'libs', include: '*.jar') // this line is necessary in order to allow gradle to take yuv.aar from "libs" dir 80 | implementation files('libs/yuv.aar') // dependency for yuv.aar library 81 | ... // other dependencies 82 | } 83 | ```` 84 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | xmlns:android 17 | 18 | ^$ 19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 | xmlns:.* 28 | 29 | ^$ 30 | 31 | 32 | BY_NAME 33 | 34 |
35 |
36 | 37 | 38 | 39 | .*:id 40 | 41 | http://schemas.android.com/apk/res/android 42 | 43 | 44 | 45 |
46 |
47 | 48 | 49 | 50 | .*:name 51 | 52 | http://schemas.android.com/apk/res/android 53 | 54 | 55 | 56 |
57 |
58 | 59 | 60 | 61 | name 62 | 63 | ^$ 64 | 65 | 66 | 67 |
68 |
69 | 70 | 71 | 72 | style 73 | 74 | ^$ 75 | 76 | 77 | 78 |
79 |
80 | 81 | 82 | 83 | .* 84 | 85 | ^$ 86 | 87 | 88 | BY_NAME 89 | 90 |
91 |
92 | 93 | 94 | 95 | .* 96 | 97 | http://schemas.android.com/apk/res/android 98 | 99 | 100 | ANDROID_ATTRIBUTE_ORDER 101 | 102 |
103 |
104 | 105 | 106 | 107 | .* 108 | 109 | .* 110 | 111 | 112 | BY_NAME 113 | 114 |
115 |
116 |
117 |
118 | 119 | 121 |
122 |
-------------------------------------------------------------------------------- /yuv/src/main/cpp/include/libyuv/cpu_id.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CPU_ID_H_ 12 | #define INCLUDE_LIBYUV_CPU_ID_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Internal flag to indicate cpuid requires initialization. 22 | static const int kCpuInitialized = 0x1; 23 | 24 | // These flags are only valid on ARM processors. 25 | static const int kCpuHasARM = 0x2; 26 | static const int kCpuHasNEON = 0x4; 27 | // 0x8 reserved for future ARM flag. 28 | 29 | // These flags are only valid on x86 processors. 30 | static const int kCpuHasX86 = 0x10; 31 | static const int kCpuHasSSE2 = 0x20; 32 | static const int kCpuHasSSSE3 = 0x40; 33 | static const int kCpuHasSSE41 = 0x80; 34 | static const int kCpuHasSSE42 = 0x100; // unused at this time. 35 | static const int kCpuHasAVX = 0x200; 36 | static const int kCpuHasAVX2 = 0x400; 37 | static const int kCpuHasERMS = 0x800; 38 | static const int kCpuHasFMA3 = 0x1000; 39 | static const int kCpuHasF16C = 0x2000; 40 | static const int kCpuHasGFNI = 0x4000; 41 | static const int kCpuHasAVX512BW = 0x8000; 42 | static const int kCpuHasAVX512VL = 0x10000; 43 | static const int kCpuHasAVX512VBMI = 0x20000; 44 | static const int kCpuHasAVX512VBMI2 = 0x40000; 45 | static const int kCpuHasAVX512VBITALG = 0x80000; 46 | static const int kCpuHasAVX512VPOPCNTDQ = 0x100000; 47 | 48 | // These flags are only valid on MIPS processors. 49 | static const int kCpuHasMIPS = 0x200000; 50 | static const int kCpuHasMSA = 0x400000; 51 | static const int kCpuHasMMI = 0x800000; 52 | 53 | // Optional init function. TestCpuFlag does an auto-init. 54 | // Returns cpu_info flags. 55 | LIBYUV_API 56 | int InitCpuFlags(void); 57 | 58 | // Detect CPU has SSE2 etc. 59 | // Test_flag parameter should be one of kCpuHas constants above. 60 | // Returns non-zero if instruction set is detected 61 | static __inline int TestCpuFlag(int test_flag) { 62 | LIBYUV_API extern int cpu_info_; 63 | #ifdef __ATOMIC_RELAXED 64 | int cpu_info = __atomic_load_n(&cpu_info_, __ATOMIC_RELAXED); 65 | #else 66 | int cpu_info = cpu_info_; 67 | #endif 68 | return (!cpu_info ? InitCpuFlags() : cpu_info) & test_flag; 69 | } 70 | 71 | // Internal function for parsing /proc/cpuinfo. 72 | LIBYUV_API 73 | int ArmCpuCaps(const char* cpuinfo_name); 74 | LIBYUV_API 75 | int MipsCpuCaps(const char* cpuinfo_name); 76 | 77 | // For testing, allow CPU flags to be disabled. 78 | // ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3. 79 | // MaskCpuFlags(-1) to enable all cpu specific optimizations. 80 | // MaskCpuFlags(1) to disable all cpu specific optimizations. 81 | // MaskCpuFlags(0) to reset state so next call will auto init. 82 | // Returns cpu_info flags. 83 | LIBYUV_API 84 | int MaskCpuFlags(int enable_flags); 85 | 86 | // Sets the CPU flags to |cpu_flags|, bypassing the detection code. |cpu_flags| 87 | // should be a valid combination of the kCpuHas constants above and include 88 | // kCpuInitialized. Use this method when running in a sandboxed process where 89 | // the detection code might fail (as it might access /proc/cpuinfo). In such 90 | // cases the cpu_info can be obtained from a non sandboxed process by calling 91 | // InitCpuFlags() and passed to the sandboxed process (via command line 92 | // parameters, IPC...) which can then call this method to initialize the CPU 93 | // flags. 94 | // Notes: 95 | // - when specifying 0 for |cpu_flags|, the auto initialization is enabled 96 | // again. 97 | // - enabling CPU features that are not supported by the CPU will result in 98 | // undefined behavior. 99 | // TODO(fbarchard): consider writing a helper function that translates from 100 | // other library CPU info to libyuv CPU info and add a .md doc that explains 101 | // CPU detection. 102 | static __inline void SetCpuFlags(int cpu_flags) { 103 | LIBYUV_API extern int cpu_info_; 104 | #ifdef __ATOMIC_RELAXED 105 | __atomic_store_n(&cpu_info_, cpu_flags, __ATOMIC_RELAXED); 106 | #else 107 | cpu_info_ = cpu_flags; 108 | #endif 109 | } 110 | 111 | // Low level cpuid for X86. Returns zeros on other CPUs. 112 | // eax is the info type that you want. 113 | // ecx is typically the cpu number, and should normally be zero. 114 | LIBYUV_API 115 | void CpuId(int info_eax, int info_ecx, int* cpu_info); 116 | 117 | #ifdef __cplusplus 118 | } // extern "C" 119 | } // namespace libyuv 120 | #endif 121 | 122 | #endif // INCLUDE_LIBYUV_CPU_ID_H_ 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/theeasiestway/libyuvwrapper/ControllerVideo.kt: -------------------------------------------------------------------------------- 1 | package com.theeasiestway.codec_h264.camera 2 | 3 | import android.content.Context 4 | import android.content.res.Configuration 5 | import android.hardware.display.DisplayManager 6 | import android.media.Image 7 | import android.util.Log 8 | import android.util.Size 9 | import android.widget.Toast 10 | import androidx.camera.core.CameraSelector 11 | import androidx.camera.core.ImageAnalysis 12 | import androidx.camera.core.Preview 13 | import androidx.camera.lifecycle.ProcessCameraProvider 14 | import androidx.camera.view.PreviewView 15 | import androidx.core.content.ContextCompat 16 | import androidx.lifecycle.LifecycleOwner 17 | import com.google.common.util.concurrent.ListenableFuture 18 | import java.lang.ref.WeakReference 19 | import java.util.concurrent.Executors 20 | 21 | // 22 | // Created by Loboda Alexey on 22.06.2020. 23 | // 24 | 25 | object ControllerVideo { 26 | 27 | private lateinit var cameraProviderFuture: ListenableFuture 28 | private lateinit var cameraProvider: ProcessCameraProvider 29 | private lateinit var displayManager: DisplayManager 30 | 31 | private val executor = Executors.newSingleThreadExecutor() 32 | private var subscriptions = HashMap Unit>() 33 | private var isLandscape = false 34 | private var rotationCurrent = 0 35 | private var displayId = -1 36 | private var released = false 37 | 38 | fun initCamera(context: Context, @CameraSelector.LensFacing lensFacing: Int, previewView: PreviewView) { 39 | val lifecycleOwner = WeakReference(context as LifecycleOwner) 40 | destroyCamera() 41 | cameraProviderFuture = ProcessCameraProvider.getInstance(context).apply { 42 | addListener(Runnable { 43 | cameraProvider = cameraProviderFuture.get() 44 | val preview = Preview.Builder().setTargetName("CameraPreview").build() 45 | preview.setSurfaceProvider(previewView.createSurfaceProvider()) 46 | startCamera(lifecycleOwner, cameraProvider, preview, lensFacing, displayId = previewView.display.displayId, onError = { 47 | Toast.makeText(context, "Unable to init camera", Toast.LENGTH_LONG).show() 48 | }) 49 | }, ContextCompat.getMainExecutor(context)) 50 | } 51 | } 52 | 53 | private fun startCamera(lifecycleOwner: WeakReference, cameraProvider: ProcessCameraProvider, preview: Preview, facing: Int, displayId: Int, onError: () -> Unit) { 54 | try { 55 | cameraProvider.unbindAll() 56 | 57 | if (lifecycleOwner.get() == null) return 58 | 59 | displayManager = (lifecycleOwner.get() as Context).getSystemService(Context.DISPLAY_SERVICE) as DisplayManager 60 | displayManager.registerDisplayListener(rotationListener, null) 61 | 62 | this.displayId = displayId 63 | 64 | rotationCurrent = displayManager.getDisplay(displayId).rotation 65 | 66 | isLandscape = (lifecycleOwner.get() as Context).resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE 67 | 68 | val cameraSelector = CameraSelector.Builder().requireLensFacing(facing).build() 69 | 70 | val imageAnalysis = ImageAnalysis.Builder() 71 | .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) 72 | .build() 73 | imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy -> 74 | if (imageProxy.image == null || imageProxy.planes.size < 3) return@Analyzer 75 | 76 | for (i in subscriptions) i.value.invoke(imageProxy.image!!) 77 | 78 | imageProxy.close() 79 | }) 80 | 81 | released = false 82 | 83 | cameraProvider.bindToLifecycle(lifecycleOwner.get()!!, cameraSelector, preview, imageAnalysis) 84 | } catch (e: Exception) { 85 | cameraProvider.unbindAll() 86 | released = true 87 | onError.invoke() 88 | } 89 | } 90 | 91 | object rotationListener : DisplayManager.DisplayListener { 92 | override fun onDisplayAdded(displayId: Int) = Unit 93 | override fun onDisplayRemoved(displayId: Int) = Unit 94 | override fun onDisplayChanged(displayId: Int) { 95 | if (ControllerVideo.displayId == displayId) 96 | rotationCurrent = displayManager.getDisplay(displayId).rotation 97 | } 98 | } 99 | 100 | fun subscribe(tag: String, onFrame: (Image) -> Unit) { 101 | subscriptions.remove(tag) 102 | subscriptions[tag] = onFrame 103 | } 104 | 105 | fun unsubscribe(tag: String) { 106 | subscriptions.remove(tag) 107 | } 108 | 109 | fun destroyCamera() { 110 | if (this::cameraProvider.isInitialized) { 111 | try { cameraProvider.unbindAll() } 112 | catch (e: Exception) { Log.e("ControllerVideo", "[destroyCamera] error: $e") } 113 | } 114 | if (this::displayManager.isInitialized) displayManager.unregisterDisplayListener(rotationListener) 115 | released = true 116 | } 117 | } -------------------------------------------------------------------------------- /yuv/src/main/cpp/include/libyuv/convert_from.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CONVERT_FROM_H_ 12 | #define INCLUDE_LIBYUV_CONVERT_FROM_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | #include "libyuv/rotate.h" 16 | 17 | #ifdef __cplusplus 18 | namespace libyuv { 19 | extern "C" { 20 | #endif 21 | 22 | // See Also convert.h for conversions from formats to I420. 23 | 24 | // Convert 8 bit YUV to 10 bit. 25 | #define H420ToH010 I420ToI010 26 | LIBYUV_API 27 | int I420ToI010(const uint8_t* src_y, 28 | int src_stride_y, 29 | const uint8_t* src_u, 30 | int src_stride_u, 31 | const uint8_t* src_v, 32 | int src_stride_v, 33 | uint16_t* dst_y, 34 | int dst_stride_y, 35 | uint16_t* dst_u, 36 | int dst_stride_u, 37 | uint16_t* dst_v, 38 | int dst_stride_v, 39 | int width, 40 | int height); 41 | 42 | LIBYUV_API 43 | int I420ToI422(const uint8_t* src_y, 44 | int src_stride_y, 45 | const uint8_t* src_u, 46 | int src_stride_u, 47 | const uint8_t* src_v, 48 | int src_stride_v, 49 | uint8_t* dst_y, 50 | int dst_stride_y, 51 | uint8_t* dst_u, 52 | int dst_stride_u, 53 | uint8_t* dst_v, 54 | int dst_stride_v, 55 | int width, 56 | int height); 57 | 58 | LIBYUV_API 59 | int I420ToI444(const uint8_t* src_y, 60 | int src_stride_y, 61 | const uint8_t* src_u, 62 | int src_stride_u, 63 | const uint8_t* src_v, 64 | int src_stride_v, 65 | uint8_t* dst_y, 66 | int dst_stride_y, 67 | uint8_t* dst_u, 68 | int dst_stride_u, 69 | uint8_t* dst_v, 70 | int dst_stride_v, 71 | int width, 72 | int height); 73 | 74 | // Copy to I400. Source can be I420, I422, I444, I400, NV12 or NV21. 75 | LIBYUV_API 76 | int I400Copy(const uint8_t* src_y, 77 | int src_stride_y, 78 | uint8_t* dst_y, 79 | int dst_stride_y, 80 | int width, 81 | int height); 82 | 83 | LIBYUV_API 84 | int I420ToNV12(const uint8_t* src_y, 85 | int src_stride_y, 86 | const uint8_t* src_u, 87 | int src_stride_u, 88 | const uint8_t* src_v, 89 | int src_stride_v, 90 | uint8_t* dst_y, 91 | int dst_stride_y, 92 | uint8_t* dst_uv, 93 | int dst_stride_uv, 94 | int width, 95 | int height); 96 | 97 | LIBYUV_API 98 | int I420ToNV21(const uint8_t* src_y, 99 | int src_stride_y, 100 | const uint8_t* src_u, 101 | int src_stride_u, 102 | const uint8_t* src_v, 103 | int src_stride_v, 104 | uint8_t* dst_y, 105 | int dst_stride_y, 106 | uint8_t* dst_vu, 107 | int dst_stride_vu, 108 | int width, 109 | int height); 110 | 111 | LIBYUV_API 112 | int I420ToYUY2(const uint8_t* src_y, 113 | int src_stride_y, 114 | const uint8_t* src_u, 115 | int src_stride_u, 116 | const uint8_t* src_v, 117 | int src_stride_v, 118 | uint8_t* dst_yuy2, 119 | int dst_stride_yuy2, 120 | int width, 121 | int height); 122 | 123 | LIBYUV_API 124 | int I420ToUYVY(const uint8_t* src_y, 125 | int src_stride_y, 126 | const uint8_t* src_u, 127 | int src_stride_u, 128 | const uint8_t* src_v, 129 | int src_stride_v, 130 | uint8_t* dst_uyvy, 131 | int dst_stride_uyvy, 132 | int width, 133 | int height); 134 | 135 | // Convert I420 to specified format. 136 | // "dst_sample_stride" is bytes in a row for the destination. Pass 0 if the 137 | // buffer has contiguous rows. Can be negative. A multiple of 16 is optimal. 138 | LIBYUV_API 139 | int ConvertFromI420(const uint8_t* y, 140 | int y_stride, 141 | const uint8_t* u, 142 | int u_stride, 143 | const uint8_t* v, 144 | int v_stride, 145 | uint8_t* dst_sample, 146 | int dst_sample_stride, 147 | int width, 148 | int height, 149 | uint32_t fourcc); 150 | 151 | #ifdef __cplusplus 152 | } // extern "C" 153 | } // namespace libyuv 154 | #endif 155 | 156 | #endif // INCLUDE_LIBYUV_CONVERT_FROM_H_ 157 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 22 | 23 | 29 | 30 | 35 | 36 | 40 | 41 | 45 | 46 | 47 | 53 | 54 | 60 | 61 | 65 | 66 | 67 | 68 |