Skip to content

Commit

Permalink
Rollback x265, added additional parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
awxkee committed Oct 13, 2024
1 parent ead58ac commit d7efa62
Show file tree
Hide file tree
Showing 25 changed files with 156 additions and 35 deletions.
14 changes: 11 additions & 3 deletions app/src/main/java/com/radzivon/bartoshyk/avif/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import androidx.lifecycle.lifecycleScope
import com.radzivon.bartoshyk.avif.coder.AvifAnimatedDecoder
import com.radzivon.bartoshyk.avif.coder.AvifChromaSubsampling
import com.radzivon.bartoshyk.avif.coder.HeifCoder
import com.radzivon.bartoshyk.avif.coder.HeifPreset
import com.radzivon.bartoshyk.avif.coder.PreciseMode
import com.radzivon.bartoshyk.avif.coder.PreferredColorConfig
import com.radzivon.bartoshyk.avif.coder.ScaleMode
Expand Down Expand Up @@ -158,9 +159,16 @@ class MainActivity : AppCompatActivity() {

Log.i("AVIFFFF", "Starts encoding")

val encode = coder.encodeAvif(bitmap = bitmap0, quality = 55, avifChromaSubsampling = AvifChromaSubsampling.YUV400)

Log.i("AVIFFFF", "Encoding time ${System.currentTimeMillis() - start}, encoded size ${encode.size}")
val encode = coder.encodeHeic(
bitmap = bitmap0,
quality = 25,
preciseMode = PreciseMode.LOSSY,
preset = HeifPreset.VERYSLOW
)
Log.i(
"AVIFFFF",
"Encoding time ${System.currentTimeMillis() - start}, encoded size ${encode.size}"
)

val bitmap = coder.decode(encode)

Expand Down
8 changes: 4 additions & 4 deletions avif-coder/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ add_library(coder SHARED JniEncoder.cpp JniException.cpp SizeScaler.cpp
colorspace/ColorMatrix.cpp imagebits/ScanAlpha.cpp imagebits/Rgba16.cpp
AvifDecoderController.cpp HeifImageDecoder.cpp JniAnimatedController.cpp)

add_library(libkvazaar SHARED IMPORTED)
add_library(libheif SHARED IMPORTED)
add_library(libyuv STATIC IMPORTED)
add_library(libde265 SHARED IMPORTED)
add_library(libdav1d SHARED IMPORTED)
add_library(libsharpyuv STATIC IMPORTED)
add_library(aom SHARED IMPORTED)
add_library(x265 SHARED IMPORTED)
add_library(avifweaver SHARED IMPORTED)

set_target_properties(libkvazaar PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libkvazaar.so)
set_target_properties(x265 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libx265.so)
set_target_properties(libheif PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libheif.so)
set_target_properties(libyuv PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libyuv.a)
set_target_properties(libde265 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libde265.so)
Expand Down Expand Up @@ -83,5 +83,5 @@ add_subdirectory(avif)

target_link_libraries( # Specifies the target library.
coder PRIVATE
${log-lib} libheif cpufeatures libyuv -ljnigraphics libkvazaar aom avif_shared
libde265 libdav1d libsharpyuv ${android-lib} avifweaver)
${log-lib} libheif cpufeatures libyuv -ljnigraphics aom avif_shared
libde265 libdav1d libsharpyuv ${android-lib} avifweaver x265)
65 changes: 58 additions & 7 deletions avif-coder/src/main/cpp/JniEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ enum AvifEncodingSurface {
};

enum AvifChromaSubsampling {
AVIF_CHROMA_AUTO, AVIF_CHROMA_YUV_420, AVIF_CHROMA_YUV_422, AVIF_CHROMA_YUV_444, AVIF_CHROMA_YUV_400
AVIF_CHROMA_AUTO,
AVIF_CHROMA_YUV_420,
AVIF_CHROMA_YUV_422,
AVIF_CHROMA_YUV_444,
AVIF_CHROMA_YUV_400
};

struct heif_error writeHeifData(struct heif_context *ctx,
Expand All @@ -95,7 +99,9 @@ jbyteArray encodeBitmapHevc(JNIEnv *env,
jobject bitmap,
const int quality,
const int dataSpace,
const bool loseless) {
const bool loseless,
std::string &x265Preset,
const int crf) {
std::shared_ptr<heif_context> ctx(heif_context_alloc(),
[](heif_context *c) { heif_context_free(c); });
if (!ctx) {
Expand Down Expand Up @@ -166,6 +172,23 @@ jbyteArray encodeBitmapHevc(JNIEnv *env,

AndroidBitmap_unlockPixels(env, bitmap);

result = heif_encoder_set_parameter(encoder.get(), "x265:preset", x265Preset.c_str());
if (result.code != heif_error_Ok) {
std::string choke(result.message);
std::string str = "Can't create encoded image with exception: " + choke;
throwException(env, str);
return static_cast<jbyteArray>(nullptr);
}

auto crfString = std::to_string(crf);
result = heif_encoder_set_parameter(encoder.get(), "x265:crf", crfString.c_str());
if (result.code != heif_error_Ok) {
std::string choke(result.message);
std::string str = "Can't create encoded image with exception: " + choke;
throwException(env, str);
return static_cast<jbyteArray>(nullptr);
}

heif_image *imagePtr;

result = heif_image_create((int) info.width, (int) info.height,
Expand Down Expand Up @@ -524,7 +547,7 @@ jbyteArray encodeBitmapAvif(JNIEnv *env,
uint8_t *uPlane = nullptr;

uint32_t vStride = 0;
uint8_t * vPlane = nullptr;
uint8_t *vPlane = nullptr;

if (pixelFormat != AVIF_PIXEL_FORMAT_YUV400) {
uStride = image->yuvRowBytes[1];
Expand Down Expand Up @@ -701,16 +724,44 @@ Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_encodeAvifImpl(JNIEnv *env,

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_encodeHeicImpl(JNIEnv *env, jobject thiz,
jobject bitmap, jint quality,
jint dataSpace, jint qualityMode) {
Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_encodeHeicImpl(JNIEnv *env,
jobject thiz,
jobject bitmap,
jint quality,
jint dataSpace,
jint qualityMode,
jint x265Preset, jint crf) {
try {
std::string preset = "superfast";
if (x265Preset == 0) {
preset = "placebo";
} else if (x265Preset == 1) {
preset = "veryslow";
} else if (x265Preset == 2) {
preset = "slower";
} else if (x265Preset == 3) {
preset = "slow";
} else if (x265Preset == 4) {
preset = "medium";
} else if (x265Preset == 5) {
preset = "fast";
} else if (x265Preset == 6) {
preset = "faster";
} else if (x265Preset == 7) {
preset = "veryfast";
} else if (x265Preset == 8) {
preset = "superfast";
} else if (x265Preset == 9) {
preset = "ultrafast";
}

return encodeBitmapHevc(env,
thiz,
bitmap,
quality,
dataSpace,
qualityMode == 2);
qualityMode == 2,
preset, crf);
} catch (std::bad_alloc &err) {
std::string exception = "Not enough memory to encode this image";
throwException(env, exception);
Expand Down
12 changes: 9 additions & 3 deletions avif-coder/src/main/cpp/SizeScaler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,20 +195,26 @@ bool RescaleImage(aligned_uint8_vector &initialData,

imageWidth = heif_image_get_width(img.get(), heif_channel_interleaved);
imageHeight = heif_image_get_height(img.get(), heif_channel_interleaved);
initialData.resize(*stride * imageHeight);

uint32_t newStride = static_cast<int >(imageWidth) * 4
* static_cast<int>(useFloats ? sizeof(uint16_t) : sizeof(uint8_t));

initialData.resize(newStride * imageHeight);

if (useFloats) {
coder::CopyUnaligned(reinterpret_cast<const uint16_t *>(data), *stride,
reinterpret_cast<uint16_t *>(initialData.data()), *stride,
reinterpret_cast<uint16_t *>(initialData.data()), newStride,
imageWidth * 4,
imageHeight);
} else {
coder::CopyUnaligned(reinterpret_cast<const uint8_t *>(data), *stride,
reinterpret_cast<uint8_t *>(initialData.data()), *stride,
reinterpret_cast<uint8_t *>(initialData.data()), newStride,
imageWidth * 4,
imageHeight);
}

*stride = static_cast<int>(newStride);

*imageWidthPtr = imageWidth;
*imageHeightPtr = imageHeight;
}
Expand Down
Binary file modified avif-coder/src/main/cpp/lib/arm64-v8a/libheif.so
Binary file not shown.
Binary file removed avif-coder/src/main/cpp/lib/arm64-v8a/libkvazaar.so
Binary file not shown.
Binary file added avif-coder/src/main/cpp/lib/arm64-v8a/libx265.so
Binary file not shown.
Binary file modified avif-coder/src/main/cpp/lib/armeabi-v7a/libheif.so
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified avif-coder/src/main/cpp/lib/x86/libheif.so
Binary file not shown.
Binary file removed avif-coder/src/main/cpp/lib/x86/libkvazaar.so
Binary file not shown.
Binary file added avif-coder/src/main/cpp/lib/x86/libx265.so
Binary file not shown.
Binary file modified avif-coder/src/main/cpp/lib/x86_64/libheif.so
Binary file not shown.
Binary file removed avif-coder/src/main/cpp/lib/x86_64/libkvazaar.so
Binary file not shown.
Binary file added avif-coder/src/main/cpp/lib/x86_64/libx265.so
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import android.content.res.AssetManager
import android.graphics.Bitmap
import android.os.Build
import android.util.Size
import androidx.annotation.IntRange
import androidx.annotation.Keep
import java.nio.ByteBuffer

Expand Down Expand Up @@ -161,18 +162,26 @@ class HeifCoder(
}
}

/**
* @param crf - consult x265 doc for crf understanding
*/
fun encodeHeic(
bitmap: Bitmap,
quality: Int = 80,
preciseMode: PreciseMode = PreciseMode.LOSSY
preciseMode: PreciseMode = PreciseMode.LOSSY,
preset: HeifPreset = HeifPreset.ULTRAFAST,
@IntRange(from = 0, to = 51) crf: Int = 40,
): ByteArray {
require(quality in 0..100) {
throw IllegalStateException("Quality should be in 0..100 range")
}
require(crf in 0..51) {
throw IllegalStateException("CRF should be in 0..51 range")
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
encodeHeicImpl(bitmap, quality, bitmap.colorSpace?.dataSpace ?: -1, preciseMode.value)
encodeHeicImpl(bitmap, quality, bitmap.colorSpace?.dataSpace ?: -1, preciseMode.value, preset.value, crf)
} else {
encodeHeicImpl(bitmap, quality, -1, preciseMode.value)
encodeHeicImpl(bitmap, quality, -1, preciseMode.value, preset.value, crf)
}
}

Expand Down Expand Up @@ -215,7 +224,9 @@ class HeifCoder(
bitmap: Bitmap,
quality: Int,
dataSpace: Int,
qualityMode: Int
qualityMode: Int,
preset: Int,
crf: Int,
): ByteArray

@SuppressLint("ObsoleteSdkInt")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* MIT License
*
* Copyright (c) 2024 Radzivon Bartoshyk
* avif-coder [/~https://github.com/awxkee/avif-coder]
*
* Created by Radzivon Bartoshyk on 13/10/2024
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/

package com.radzivon.bartoshyk.avif.coder

import androidx.annotation.Keep

@Keep
/**
* See https://x265.readthedocs.io/en/stable/presets.html for more info
*/
enum class HeifPreset(internal val value: Int) {
PLACEBO(0),
VERYSLOW(1),
SLOWER(2),
SLOW(3),
MEDIUM(4),
FAST(5),
FASTER(6),
VERYFAST(7),
SUPERFAST(8),
ULTRAFAST(9),
}
2 changes: 1 addition & 1 deletion build_dav1d.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#

set -e
export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"

destination_directory=dav1d
if [ ! -d "$destination_directory" ]; then
git clone https://code.videolan.org/videolan/dav1d -b 1.4.3
Expand Down
1 change: 0 additions & 1 deletion build_de265.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

set -e

export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"
export NDK=$NDK_PATH

destination_directory=libde265
Expand Down
12 changes: 6 additions & 6 deletions build_heif.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#

set -e
export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"
export NDK=$NDK_PATH

destination_directory=libheif
Expand All @@ -47,8 +46,8 @@ for abi in ${ABI_LIST}; do
cp -r ./../../libde265/build-${abi}/libde265/de265-version.h ../../libde265/libde265/de265-version.h
cp -r ./../../x265_git/build-${abi}/x265_config.h ./../../x265_git/source/x265_config.h
cp -r ./../../dav1d/build-${abi}/include/dav1d/version.h ./../../dav1d/include/dav1d/version.h
mkdir -p ./../../SVT-AV1/svt-av1
cp -r ./../../SVT-AV1/Source/API/* ./../../SVT-AV1/svt-av1
# mkdir -p ./../../SVT-AV1/svt-av1
# cp -r ./../../SVT-AV1/Source/API/* ./../../SVT-AV1/svt-av1
cmake .. \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
Expand All @@ -63,9 +62,10 @@ for abi in ${ABI_LIST}; do
-DAOM_ENCODER=OFF \
-DWITH_AOM_DECODER=OFF \
-DWITH_KVAZAAR=ON \
-DKVAZAAR_INCLUDE_DIR=../../kvazaar/src \
-DKVAZAAR_LIBRARY=../../kvazaar/build-${abi}/libkvazaar.so \
-DLIBDE265_LIBRARY=../../libde265/build-${abi}/libde265/libde265.so \
-DWITH_X265=ON \
-DX265_INCLUDE_DIR=./../../x265_git/source \
-DX265_LIBRARY=./../../x265_git/build-${abi}/libx265.so \
-DLIBDE265_LIBRARY=./../../libde265/build-${abi}/libde265/libde265.so \
-DLIBDE265_INCLUDE_DIR=../../libde265 \
-DLIBSHARPYUV_INCLUDE_DIR=../../libwebp \
-DLIBSHARPYUV_LIBRARY=../../libwebp/build-${abi}/libsharpyuv.a \
Expand Down
2 changes: 1 addition & 1 deletion build_kvazaar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#

set -e
export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"

export NDK=$NDK_PATH

destination_directory=kvazaar
Expand Down
1 change: 0 additions & 1 deletion build_sharpyuv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

set -e

export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"
export NDK=$NDK_PATH

destination_directory=libwebp
Expand Down
1 change: 0 additions & 1 deletion build_svt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#

set -e
export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"
export NDK=$NDK_PATH

destination_directory=SVT-AV1
Expand Down
6 changes: 3 additions & 3 deletions build_x265.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ export NDK=$NDK_PATH

destination_directory=x265_git
if [ ! -d "$destination_directory" ]; then
git clone https://bitbucket.org/multicoreware/x265_git.git -b 3.6
git clone https://bitbucket.org/multicoreware/x265_git.git -b 4.0
else
echo "Destination directory '$destination_directory' already exists. Cloning skipped."
fi

cd x265_git

#ABI_LIST="armeabi-v7a arm64-v8a x86 x86_64"
ABI_LIST="armeabi-v7a arm64-v8a x86 x86_64"

ABI_LIST="arm64-v8a"
#ABI_LIST="arm64-v8a"

for abi in ${ABI_LIST}; do
rm -rf "build-${abi}"
Expand Down

0 comments on commit d7efa62

Please sign in to comment.