Skip to content

Commit d7efa62

Browse files
committed
Rollback x265, added additional parameters
1 parent ead58ac commit d7efa62

25 files changed

+156
-35
lines changed

app/src/main/java/com/radzivon/bartoshyk/avif/MainActivity.kt

+11-3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import androidx.lifecycle.lifecycleScope
3939
import com.radzivon.bartoshyk.avif.coder.AvifAnimatedDecoder
4040
import com.radzivon.bartoshyk.avif.coder.AvifChromaSubsampling
4141
import com.radzivon.bartoshyk.avif.coder.HeifCoder
42+
import com.radzivon.bartoshyk.avif.coder.HeifPreset
4243
import com.radzivon.bartoshyk.avif.coder.PreciseMode
4344
import com.radzivon.bartoshyk.avif.coder.PreferredColorConfig
4445
import com.radzivon.bartoshyk.avif.coder.ScaleMode
@@ -158,9 +159,16 @@ class MainActivity : AppCompatActivity() {
158159

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

161-
val encode = coder.encodeAvif(bitmap = bitmap0, quality = 55, avifChromaSubsampling = AvifChromaSubsampling.YUV400)
162-
163-
Log.i("AVIFFFF", "Encoding time ${System.currentTimeMillis() - start}, encoded size ${encode.size}")
162+
val encode = coder.encodeHeic(
163+
bitmap = bitmap0,
164+
quality = 25,
165+
preciseMode = PreciseMode.LOSSY,
166+
preset = HeifPreset.VERYSLOW
167+
)
168+
Log.i(
169+
"AVIFFFF",
170+
"Encoding time ${System.currentTimeMillis() - start}, encoded size ${encode.size}"
171+
)
164172

165173
val bitmap = coder.decode(encode)
166174

avif-coder/src/main/cpp/CMakeLists.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ add_library(coder SHARED JniEncoder.cpp JniException.cpp SizeScaler.cpp
2121
colorspace/ColorMatrix.cpp imagebits/ScanAlpha.cpp imagebits/Rgba16.cpp
2222
AvifDecoderController.cpp HeifImageDecoder.cpp JniAnimatedController.cpp)
2323

24-
add_library(libkvazaar SHARED IMPORTED)
2524
add_library(libheif SHARED IMPORTED)
2625
add_library(libyuv STATIC IMPORTED)
2726
add_library(libde265 SHARED IMPORTED)
2827
add_library(libdav1d SHARED IMPORTED)
2928
add_library(libsharpyuv STATIC IMPORTED)
3029
add_library(aom SHARED IMPORTED)
30+
add_library(x265 SHARED IMPORTED)
3131
add_library(avifweaver SHARED IMPORTED)
3232

33-
set_target_properties(libkvazaar PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libkvazaar.so)
33+
set_target_properties(x265 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libx265.so)
3434
set_target_properties(libheif PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libheif.so)
3535
set_target_properties(libyuv PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libyuv.a)
3636
set_target_properties(libde265 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libde265.so)
@@ -83,5 +83,5 @@ add_subdirectory(avif)
8383

8484
target_link_libraries( # Specifies the target library.
8585
coder PRIVATE
86-
${log-lib} libheif cpufeatures libyuv -ljnigraphics libkvazaar aom avif_shared
87-
libde265 libdav1d libsharpyuv ${android-lib} avifweaver)
86+
${log-lib} libheif cpufeatures libyuv -ljnigraphics aom avif_shared
87+
libde265 libdav1d libsharpyuv ${android-lib} avifweaver x265)

avif-coder/src/main/cpp/JniEncoder.cpp

+58-7
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ enum AvifEncodingSurface {
7070
};
7171

7272
enum AvifChromaSubsampling {
73-
AVIF_CHROMA_AUTO, AVIF_CHROMA_YUV_420, AVIF_CHROMA_YUV_422, AVIF_CHROMA_YUV_444, AVIF_CHROMA_YUV_400
73+
AVIF_CHROMA_AUTO,
74+
AVIF_CHROMA_YUV_420,
75+
AVIF_CHROMA_YUV_422,
76+
AVIF_CHROMA_YUV_444,
77+
AVIF_CHROMA_YUV_400
7478
};
7579

7680
struct heif_error writeHeifData(struct heif_context *ctx,
@@ -95,7 +99,9 @@ jbyteArray encodeBitmapHevc(JNIEnv *env,
9599
jobject bitmap,
96100
const int quality,
97101
const int dataSpace,
98-
const bool loseless) {
102+
const bool loseless,
103+
std::string &x265Preset,
104+
const int crf) {
99105
std::shared_ptr<heif_context> ctx(heif_context_alloc(),
100106
[](heif_context *c) { heif_context_free(c); });
101107
if (!ctx) {
@@ -166,6 +172,23 @@ jbyteArray encodeBitmapHevc(JNIEnv *env,
166172

167173
AndroidBitmap_unlockPixels(env, bitmap);
168174

175+
result = heif_encoder_set_parameter(encoder.get(), "x265:preset", x265Preset.c_str());
176+
if (result.code != heif_error_Ok) {
177+
std::string choke(result.message);
178+
std::string str = "Can't create encoded image with exception: " + choke;
179+
throwException(env, str);
180+
return static_cast<jbyteArray>(nullptr);
181+
}
182+
183+
auto crfString = std::to_string(crf);
184+
result = heif_encoder_set_parameter(encoder.get(), "x265:crf", crfString.c_str());
185+
if (result.code != heif_error_Ok) {
186+
std::string choke(result.message);
187+
std::string str = "Can't create encoded image with exception: " + choke;
188+
throwException(env, str);
189+
return static_cast<jbyteArray>(nullptr);
190+
}
191+
169192
heif_image *imagePtr;
170193

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

526549
uint32_t vStride = 0;
527-
uint8_t * vPlane = nullptr;
550+
uint8_t *vPlane = nullptr;
528551

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

702725
extern "C"
703726
JNIEXPORT jbyteArray JNICALL
704-
Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_encodeHeicImpl(JNIEnv *env, jobject thiz,
705-
jobject bitmap, jint quality,
706-
jint dataSpace, jint qualityMode) {
727+
Java_com_radzivon_bartoshyk_avif_coder_HeifCoder_encodeHeicImpl(JNIEnv *env,
728+
jobject thiz,
729+
jobject bitmap,
730+
jint quality,
731+
jint dataSpace,
732+
jint qualityMode,
733+
jint x265Preset, jint crf) {
707734
try {
735+
std::string preset = "superfast";
736+
if (x265Preset == 0) {
737+
preset = "placebo";
738+
} else if (x265Preset == 1) {
739+
preset = "veryslow";
740+
} else if (x265Preset == 2) {
741+
preset = "slower";
742+
} else if (x265Preset == 3) {
743+
preset = "slow";
744+
} else if (x265Preset == 4) {
745+
preset = "medium";
746+
} else if (x265Preset == 5) {
747+
preset = "fast";
748+
} else if (x265Preset == 6) {
749+
preset = "faster";
750+
} else if (x265Preset == 7) {
751+
preset = "veryfast";
752+
} else if (x265Preset == 8) {
753+
preset = "superfast";
754+
} else if (x265Preset == 9) {
755+
preset = "ultrafast";
756+
}
757+
708758
return encodeBitmapHevc(env,
709759
thiz,
710760
bitmap,
711761
quality,
712762
dataSpace,
713-
qualityMode == 2);
763+
qualityMode == 2,
764+
preset, crf);
714765
} catch (std::bad_alloc &err) {
715766
std::string exception = "Not enough memory to encode this image";
716767
throwException(env, exception);

avif-coder/src/main/cpp/SizeScaler.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,26 @@ bool RescaleImage(aligned_uint8_vector &initialData,
195195

196196
imageWidth = heif_image_get_width(img.get(), heif_channel_interleaved);
197197
imageHeight = heif_image_get_height(img.get(), heif_channel_interleaved);
198-
initialData.resize(*stride * imageHeight);
198+
199+
uint32_t newStride = static_cast<int >(imageWidth) * 4
200+
* static_cast<int>(useFloats ? sizeof(uint16_t) : sizeof(uint8_t));
201+
202+
initialData.resize(newStride * imageHeight);
199203

200204
if (useFloats) {
201205
coder::CopyUnaligned(reinterpret_cast<const uint16_t *>(data), *stride,
202-
reinterpret_cast<uint16_t *>(initialData.data()), *stride,
206+
reinterpret_cast<uint16_t *>(initialData.data()), newStride,
203207
imageWidth * 4,
204208
imageHeight);
205209
} else {
206210
coder::CopyUnaligned(reinterpret_cast<const uint8_t *>(data), *stride,
207-
reinterpret_cast<uint8_t *>(initialData.data()), *stride,
211+
reinterpret_cast<uint8_t *>(initialData.data()), newStride,
208212
imageWidth * 4,
209213
imageHeight);
210214
}
211215

216+
*stride = static_cast<int>(newStride);
217+
212218
*imageWidthPtr = imageWidth;
213219
*imageHeightPtr = imageHeight;
214220
}
10.9 KB
Binary file not shown.
Binary file not shown.
1.86 MB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8.76 KB
Binary file not shown.
-520 KB
Binary file not shown.
2.18 MB
Binary file not shown.
9.13 KB
Binary file not shown.
-621 KB
Binary file not shown.
2.2 MB
Binary file not shown.

avif-coder/src/main/java/com/radzivon/bartoshyk/avif/coder/HeifCoder.kt

+15-4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import android.content.res.AssetManager
3636
import android.graphics.Bitmap
3737
import android.os.Build
3838
import android.util.Size
39+
import androidx.annotation.IntRange
3940
import androidx.annotation.Keep
4041
import java.nio.ByteBuffer
4142

@@ -161,18 +162,26 @@ class HeifCoder(
161162
}
162163
}
163164

165+
/**
166+
* @param crf - consult x265 doc for crf understanding
167+
*/
164168
fun encodeHeic(
165169
bitmap: Bitmap,
166170
quality: Int = 80,
167-
preciseMode: PreciseMode = PreciseMode.LOSSY
171+
preciseMode: PreciseMode = PreciseMode.LOSSY,
172+
preset: HeifPreset = HeifPreset.ULTRAFAST,
173+
@IntRange(from = 0, to = 51) crf: Int = 40,
168174
): ByteArray {
169175
require(quality in 0..100) {
170176
throw IllegalStateException("Quality should be in 0..100 range")
171177
}
178+
require(crf in 0..51) {
179+
throw IllegalStateException("CRF should be in 0..51 range")
180+
}
172181
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
173-
encodeHeicImpl(bitmap, quality, bitmap.colorSpace?.dataSpace ?: -1, preciseMode.value)
182+
encodeHeicImpl(bitmap, quality, bitmap.colorSpace?.dataSpace ?: -1, preciseMode.value, preset.value, crf)
174183
} else {
175-
encodeHeicImpl(bitmap, quality, -1, preciseMode.value)
184+
encodeHeicImpl(bitmap, quality, -1, preciseMode.value, preset.value, crf)
176185
}
177186
}
178187

@@ -215,7 +224,9 @@ class HeifCoder(
215224
bitmap: Bitmap,
216225
quality: Int,
217226
dataSpace: Int,
218-
qualityMode: Int
227+
qualityMode: Int,
228+
preset: Int,
229+
crf: Int,
219230
): ByteArray
220231

221232
@SuppressLint("ObsoleteSdkInt")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2024 Radzivon Bartoshyk
5+
* avif-coder [https://github.com/awxkee/avif-coder]
6+
*
7+
* Created by Radzivon Bartoshyk on 13/10/2024
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in all
17+
* copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
* SOFTWARE.
26+
*
27+
*/
28+
29+
package com.radzivon.bartoshyk.avif.coder
30+
31+
import androidx.annotation.Keep
32+
33+
@Keep
34+
/**
35+
* See https://x265.readthedocs.io/en/stable/presets.html for more info
36+
*/
37+
enum class HeifPreset(internal val value: Int) {
38+
PLACEBO(0),
39+
VERYSLOW(1),
40+
SLOWER(2),
41+
SLOW(3),
42+
MEDIUM(4),
43+
FAST(5),
44+
FASTER(6),
45+
VERYFAST(7),
46+
SUPERFAST(8),
47+
ULTRAFAST(9),
48+
}

build_dav1d.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#
2626

2727
set -e
28-
export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"
28+
2929
destination_directory=dav1d
3030
if [ ! -d "$destination_directory" ]; then
3131
git clone https://code.videolan.org/videolan/dav1d -b 1.4.3

build_de265.sh

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
set -e
2828

29-
export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"
3029
export NDK=$NDK_PATH
3130

3231
destination_directory=libde265

build_heif.sh

+6-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#
2626

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

3130
destination_directory=libheif
@@ -47,8 +46,8 @@ for abi in ${ABI_LIST}; do
4746
cp -r ./../../libde265/build-${abi}/libde265/de265-version.h ../../libde265/libde265/de265-version.h
4847
cp -r ./../../x265_git/build-${abi}/x265_config.h ./../../x265_git/source/x265_config.h
4948
cp -r ./../../dav1d/build-${abi}/include/dav1d/version.h ./../../dav1d/include/dav1d/version.h
50-
mkdir -p ./../../SVT-AV1/svt-av1
51-
cp -r ./../../SVT-AV1/Source/API/* ./../../SVT-AV1/svt-av1
49+
# mkdir -p ./../../SVT-AV1/svt-av1
50+
# cp -r ./../../SVT-AV1/Source/API/* ./../../SVT-AV1/svt-av1
5251
cmake .. \
5352
-G Ninja \
5453
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
@@ -63,9 +62,10 @@ for abi in ${ABI_LIST}; do
6362
-DAOM_ENCODER=OFF \
6463
-DWITH_AOM_DECODER=OFF \
6564
-DWITH_KVAZAAR=ON \
66-
-DKVAZAAR_INCLUDE_DIR=../../kvazaar/src \
67-
-DKVAZAAR_LIBRARY=../../kvazaar/build-${abi}/libkvazaar.so \
68-
-DLIBDE265_LIBRARY=../../libde265/build-${abi}/libde265/libde265.so \
65+
-DWITH_X265=ON \
66+
-DX265_INCLUDE_DIR=./../../x265_git/source \
67+
-DX265_LIBRARY=./../../x265_git/build-${abi}/libx265.so \
68+
-DLIBDE265_LIBRARY=./../../libde265/build-${abi}/libde265/libde265.so \
6969
-DLIBDE265_INCLUDE_DIR=../../libde265 \
7070
-DLIBSHARPYUV_INCLUDE_DIR=../../libwebp \
7171
-DLIBSHARPYUV_LIBRARY=../../libwebp/build-${abi}/libsharpyuv.a \

build_kvazaar.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#
2929

3030
set -e
31-
export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"
31+
3232
export NDK=$NDK_PATH
3333

3434
destination_directory=kvazaar

build_sharpyuv.sh

-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
set -e
2828

29-
export NDK_PATH="/Users/radzivon/Library/Android/sdk/ndk/27.0.12077973"
3029
export NDK=$NDK_PATH
3130

3231
destination_directory=libwebp

build_svt.sh

-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#
2626

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

3130
destination_directory=SVT-AV1

build_x265.sh

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ export NDK=$NDK_PATH
3030

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

3838
cd x265_git
3939

40-
#ABI_LIST="armeabi-v7a arm64-v8a x86 x86_64"
40+
ABI_LIST="armeabi-v7a arm64-v8a x86 x86_64"
4141

42-
ABI_LIST="arm64-v8a"
42+
#ABI_LIST="arm64-v8a"
4343

4444
for abi in ${ABI_LIST}; do
4545
rm -rf "build-${abi}"

0 commit comments

Comments
 (0)