Skip to content

Commit bf20eba

Browse files
committed
Added custom YUV decoding, bump to 2.0.6
1 parent d088c2e commit bf20eba

File tree

15 files changed

+887
-37
lines changed

15 files changed

+887
-37
lines changed

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

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class MainActivity : AppCompatActivity() {
122122
var allFiles = mutableListOf<String>()
123123
allFiles.addAll(allFiles2)
124124
allFiles.addAll(allFiles1)
125-
allFiles = allFiles.filter { it.contains("hato-wide-gamut-8bit.avif") }.toMutableList()
125+
allFiles = allFiles.filter { it.contains("bt_2020_pq.avif") }.toMutableList()
126126
// allFiles = allFiles.filter { it.contains("bbb_alpha_inverted.avif") }.toMutableList()
127127
for (file in allFiles) {
128128
try {
@@ -139,7 +139,6 @@ class MainActivity : AppCompatActivity() {
139139
// PreferredColorConfig.RGBA_1010102,
140140
// ScaleMode.RESIZE
141141
// )
142-
143142
var start = System.currentTimeMillis()
144143

145144
var bitmap0 = coder.decode(
@@ -149,16 +148,12 @@ class MainActivity : AppCompatActivity() {
149148

150149
Log.d("AVIFFFF", "Decode time ${System.currentTimeMillis() - start}")
151150

152-
// val encode = coder.encodeHeic(bitmap0)
151+
val encode = coder.encodeAvif(bitmap0, avifChromaSubsampling = AvifChromaSubsampling.YUV400)
153152
//
154-
// val round = coder.decodeSampled(
155-
// byteArray = encode,
156-
// scaledWidth = 700,
157-
// scaledHeight = 700,
158-
// preferredColorConfig = PreferredColorConfig.RGBA_8888,
159-
// scaleMode = ScaleMode.FIT,
160-
// scaleQuality = ScalingQuality.DEFAULT,
161-
// )
153+
val round = coder.decode(
154+
byteArray = encode,
155+
preferredColorConfig = PreferredColorConfig.RGBA_8888,
156+
)
162157

163158
// bitmap0.setColorSpace(ColorSpace.getFromDataSpace(DataSpace.DATASPACE_BT2020_PQ)!!)
164159

@@ -171,15 +166,15 @@ class MainActivity : AppCompatActivity() {
171166
imageView.root.setImageBitmap(bitmap0)
172167
binding.scrollViewContainer.addView(imageView.root)
173168
}
174-
// lifecycleScope.launch(Dispatchers.Main) {
175-
// val imageView = BindingImageViewBinding.inflate(
176-
// layoutInflater,
177-
// binding.scrollViewContainer,
178-
// false
179-
// )
180-
// imageView.root.setImageBitmap(round)
181-
// binding.scrollViewContainer.addView(imageView.root)
182-
// }
169+
lifecycleScope.launch(Dispatchers.Main) {
170+
val imageView = BindingImageViewBinding.inflate(
171+
layoutInflater,
172+
binding.scrollViewContainer,
173+
false
174+
)
175+
imageView.root.setImageBitmap(round)
176+
binding.scrollViewContainer.addView(imageView.root)
177+
}
183178
}
184179
} catch (e: Exception) {
185180
Log.d("AVIF", e.toString())

avif-coder/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ afterEvaluate {
4242
create<MavenPublication>("mavenJava") {
4343
groupId = "com.github.awxkee"
4444
artifactId = "avif-coder"
45-
version = "2.0.1"
45+
version = "2.0.6"
4646
from(components["release"])
4747
// artifact("androidSourcesJar")
4848
}

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

Lines changed: 163 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <ITUR.h>
3939
#include "ColorMatrix.h"
4040
#include "avifweaver.h"
41+
#include <android/log.h>
4142

4243
class AvifUniqueImage {
4344
public:
@@ -123,13 +124,172 @@ AvifImageFrame AvifDecoderController::getFrame(uint32_t frame,
123124
str = "Can't correctly allocate buffer for frame with numbers: " + std::to_string(frame);
124125
throw std::runtime_error(str);
125126
}
126-
rgbResult = avifImageYUVToRGB(decoder->image, &avifUniqueImage.rgbImage);
127-
if (rgbResult != AVIF_RESULT_OK) {
127+
128+
bool isImageConverted = false;
129+
130+
auto image = decoder->image;
131+
132+
auto type = decoder->image->yuvFormat;
133+
134+
YuvMatrix matrix = YuvMatrix::Bt709;
135+
if (image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT601) {
136+
matrix = YuvMatrix::Bt601;
137+
} else if (image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT2020_NCL
138+
|| image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_SMPTE2085) {
139+
matrix = YuvMatrix::Bt2020;
140+
}
141+
142+
YuvRange range = YuvRange::Tv;
143+
if (image->yuvRange == AVIF_RANGE_FULL) {
144+
range = YuvRange::Pc;
145+
}
146+
147+
YuvType yuvType = YuvType::Yuv420;
148+
if (type == AVIF_PIXEL_FORMAT_YUV422) {
149+
yuvType = YuvType::Yuv422;
150+
} else if (type == AVIF_PIXEL_FORMAT_YUV444) {
151+
yuvType = YuvType::Yuv444;
152+
}
153+
154+
auto start = std::chrono::high_resolution_clock::now();
155+
156+
if (type == AVIF_PIXEL_FORMAT_YUV444 || type == AVIF_PIXEL_FORMAT_YUV422
157+
|| type == AVIF_PIXEL_FORMAT_YUV420) {
158+
159+
if (isImageRequires64Bit) {
160+
if (imageUsesAlpha) {
161+
weave_yuv16_with_alpha_to_rgba16(
162+
reinterpret_cast<const uint16_t *>(image->yuvPlanes[0]),
163+
image->yuvRowBytes[0],
164+
reinterpret_cast<const uint16_t *>(image->yuvPlanes[1]),
165+
image->yuvRowBytes[1],
166+
reinterpret_cast<const uint16_t *>(image->yuvPlanes[2]),
167+
image->yuvRowBytes[2],
168+
reinterpret_cast<const uint16_t *>(image->alphaPlane),
169+
image->alphaRowBytes,
170+
reinterpret_cast<uint16_t *>(avifUniqueImage.rgbImage.pixels),
171+
avifUniqueImage.rgbImage.rowBytes,
172+
bitDepth,
173+
avifUniqueImage.rgbImage.width,
174+
avifUniqueImage.rgbImage.height,
175+
range,
176+
matrix,
177+
yuvType
178+
);
179+
isImageConverted = true;
180+
} else {
181+
weave_yuv16_to_rgba16(
182+
reinterpret_cast<const uint16_t *>(image->yuvPlanes[0]),
183+
image->yuvRowBytes[0],
184+
reinterpret_cast<const uint16_t *>(image->yuvPlanes[1]),
185+
image->yuvRowBytes[1],
186+
reinterpret_cast<const uint16_t *>(image->yuvPlanes[2]),
187+
image->yuvRowBytes[2],
188+
reinterpret_cast<uint16_t *>(avifUniqueImage.rgbImage.pixels),
189+
avifUniqueImage.rgbImage.rowBytes,
190+
bitDepth,
191+
avifUniqueImage.rgbImage.width,
192+
avifUniqueImage.rgbImage.height,
193+
range,
194+
matrix,
195+
yuvType
196+
);
197+
isImageConverted = true;
198+
}
199+
} else {
200+
if (imageUsesAlpha) {
201+
weave_yuv8_with_alpha_to_rgba8(
202+
image->yuvPlanes[0], image->yuvRowBytes[0],
203+
image->yuvPlanes[1], image->yuvRowBytes[1],
204+
image->yuvPlanes[2], image->yuvRowBytes[2],
205+
image->alphaPlane, image->alphaRowBytes,
206+
avifUniqueImage.rgbImage.pixels, avifUniqueImage.rgbImage.rowBytes,
207+
avifUniqueImage.rgbImage.width, avifUniqueImage.rgbImage.height,
208+
range, matrix, yuvType
209+
);
210+
isImageConverted = true;
211+
} else {
212+
weave_yuv8_to_rgba8(
213+
image->yuvPlanes[0], image->yuvRowBytes[0],
214+
image->yuvPlanes[1], image->yuvRowBytes[1],
215+
image->yuvPlanes[2], image->yuvRowBytes[2],
216+
avifUniqueImage.rgbImage.pixels, avifUniqueImage.rgbImage.rowBytes,
217+
avifUniqueImage.rgbImage.width, avifUniqueImage.rgbImage.height,
218+
range, matrix, yuvType
219+
);
220+
isImageConverted = true;
221+
}
222+
}
223+
} else if (type == AVIF_PIXEL_FORMAT_YUV400) {
224+
if (isImageRequires64Bit) {
225+
if (imageUsesAlpha) {
226+
weave_yuv400_p16_with_alpha_to_rgba16(
227+
reinterpret_cast<const uint16_t *>(image->yuvPlanes[0]),
228+
image->yuvRowBytes[0],
229+
reinterpret_cast<const uint16_t *>(image->alphaPlane),
230+
image->alphaRowBytes,
231+
reinterpret_cast<uint16_t *>(avifUniqueImage.rgbImage.pixels),
232+
avifUniqueImage.rgbImage.rowBytes,
233+
bitDepth,
234+
avifUniqueImage.rgbImage.width,
235+
avifUniqueImage.rgbImage.height,
236+
range,
237+
matrix
238+
);
239+
} else {
240+
weave_yuv400_p16_to_rgba16(
241+
reinterpret_cast<const uint16_t *>(image->yuvPlanes[0]),
242+
image->yuvRowBytes[0],
243+
reinterpret_cast<uint16_t *>(avifUniqueImage.rgbImage.pixels),
244+
avifUniqueImage.rgbImage.rowBytes,
245+
bitDepth,
246+
avifUniqueImage.rgbImage.width,
247+
avifUniqueImage.rgbImage.height,
248+
range,
249+
matrix
250+
);
251+
}
252+
isImageConverted = true;
253+
} else {
254+
if (imageUsesAlpha) {
255+
weave_yuv400_with_alpha_to_rgba8(
256+
reinterpret_cast<const uint8_t *>(image->yuvPlanes[0]),
257+
image->yuvRowBytes[0],
258+
image->alphaPlane, image->alphaRowBytes,
259+
reinterpret_cast<uint8_t *>(avifUniqueImage.rgbImage.pixels),
260+
avifUniqueImage.rgbImage.rowBytes,
261+
avifUniqueImage.rgbImage.width,
262+
avifUniqueImage.rgbImage.height,
263+
range,
264+
matrix
265+
);
266+
} else {
267+
weave_yuv400_to_rgba8(
268+
reinterpret_cast<const uint8_t *>(image->yuvPlanes[0]),
269+
image->yuvRowBytes[0],
270+
reinterpret_cast<uint8_t *>(avifUniqueImage.rgbImage.pixels),
271+
avifUniqueImage.rgbImage.rowBytes,
272+
avifUniqueImage.rgbImage.width,
273+
avifUniqueImage.rgbImage.height,
274+
range,
275+
matrix
276+
);
277+
}
278+
isImageConverted = true;
279+
}
280+
}
281+
282+
if (!isImageConverted) {
128283
std::string
129-
str = "Can't correctly allocate buffer for frame with numbers: " + std::to_string(frame);
284+
str = "Unfortunately image type is not supported" + std::to_string(frame);
130285
throw std::runtime_error(str);
131286
}
132287

288+
auto end = std::chrono::high_resolution_clock::now();
289+
std::chrono::duration<double> duration = end - start;
290+
auto count = (float) (duration.count() * 1000.0);
291+
__android_log_print(ANDROID_LOG_ERROR, "AVIFCoder", "YUV Conversion time %f", count);
292+
133293
aligned_uint8_vector iccProfile(0);
134294
if (decoder->image->icc.data && decoder->image->icc.size) {
135295
iccProfile.resize(decoder->image->icc.size);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ set(CMAKE_CXX_STANDARD 20)
6060
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6161
if (CMAKE_BUILD_TYPE STREQUAL "Release")
6262
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -ffp-mode=fast")
63+
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
6364
endif ()
6465
add_definitions(-DCMS_NO_REGISTER_KEYWORD -DSTB_IMAGE_RESIZE_IMPLEMENTATION)
6566

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ add_library(avif_shared STATIC alpha.c avif.c colr.c colrconvert.c codec_aom.c
99
rawdata.c read.c reformat.c reformat_libyuv.c
1010
scale.c stream.c utils.c write.c codec_dav1d.c reformat_libsharpyuv.c)
1111

12-
target_compile_definitions(avif_shared PRIVATE AVIF_CODEC_AOM_ENCODE AVIF_CODEC_AOM AVIF_LIBYUV_ENABLED AVIF_CODEC_DAV1D)
12+
target_compile_definitions(avif_shared PRIVATE AVIF_CODEC_AOM_ENCODE AVIF_CODEC_AOM AVIF_CODEC_DAV1D)
1313

1414
target_include_directories(avif_shared PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/..
1515
${CMAKE_SOURCE_DIR}/avif ${CMAKE_SOURCE_DIR}/libyuv)

avif-coder/src/main/cpp/avifweaver.h

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
#include <new>
66

77
enum class YuvMatrix {
8-
Bt601 = 0,
9-
Bt709 = 1,
10-
Bt2020 = 2,
8+
Bt601,
9+
Bt709,
10+
Bt2020,
1111
};
1212

13-
enum class YuvStandardRange {
13+
enum class YuvRange {
1414
Tv,
1515
Pc,
1616
};
@@ -30,13 +30,55 @@ void weave_yuv8_to_rgba8(const uint8_t *y_plane,
3030
const uint8_t *v_plane,
3131
uint32_t v_stride,
3232
uint8_t *rgba,
33-
uint32_t dst_stride,
33+
uint32_t rgba_stride,
3434
uint32_t width,
3535
uint32_t height,
36-
YuvStandardRange range,
37-
YuvMatrix matrix,
36+
YuvRange range,
37+
YuvMatrix yuv_matrix,
3838
YuvType yuv_type);
3939

40+
void weave_yuv400_to_rgba8(const uint8_t *y_plane,
41+
uint32_t y_stride,
42+
uint8_t *rgba,
43+
uint32_t rgba_stride,
44+
uint32_t width,
45+
uint32_t height,
46+
YuvRange range,
47+
YuvMatrix yuv_matrix);
48+
49+
void weave_yuv400_with_alpha_to_rgba8(const uint8_t *y_plane,
50+
uint32_t y_stride,
51+
const uint8_t *a_plane,
52+
uint32_t a_stride,
53+
uint8_t *rgba,
54+
uint32_t rgba_stride,
55+
uint32_t width,
56+
uint32_t height,
57+
YuvRange range,
58+
YuvMatrix yuv_matrix);
59+
60+
void weave_yuv400_p16_to_rgba16(const uint16_t *y_plane,
61+
uint32_t y_stride,
62+
uint16_t *rgba,
63+
uint32_t rgba_stride,
64+
uint32_t bit_depth,
65+
uint32_t width,
66+
uint32_t height,
67+
YuvRange range,
68+
YuvMatrix yuv_matrix);
69+
70+
void weave_yuv400_p16_with_alpha_to_rgba16(const uint16_t *y_plane,
71+
uint32_t y_stride,
72+
const uint16_t *a_plane,
73+
uint32_t a_stride,
74+
uint16_t *rgba,
75+
uint32_t rgba_stride,
76+
uint32_t bit_depth,
77+
uint32_t width,
78+
uint32_t height,
79+
YuvRange range,
80+
YuvMatrix yuv_matrix);
81+
4082
void weave_yuv8_with_alpha_to_rgba8(const uint8_t *y_plane,
4183
uint32_t y_stride,
4284
const uint8_t *u_plane,
@@ -46,13 +88,45 @@ void weave_yuv8_with_alpha_to_rgba8(const uint8_t *y_plane,
4688
const uint8_t *a_plane,
4789
uint32_t a_stride,
4890
uint8_t *rgba,
49-
uint32_t dst_stride,
91+
uint32_t rgba_stride,
5092
uint32_t width,
5193
uint32_t height,
52-
YuvStandardRange range,
53-
YuvMatrix matrix,
94+
YuvRange range,
95+
YuvMatrix yuv_matrix,
5496
YuvType yuv_type);
5597

98+
void weave_yuv16_to_rgba16(const uint16_t *y_plane,
99+
uint32_t y_stride,
100+
const uint16_t *u_plane,
101+
uint32_t u_stride,
102+
const uint16_t *v_plane,
103+
uint32_t v_stride,
104+
uint16_t *rgba,
105+
uint32_t rgba_stride,
106+
uint32_t bit_depth,
107+
uint32_t width,
108+
uint32_t height,
109+
YuvRange range,
110+
YuvMatrix yuv_matrix,
111+
YuvType yuv_type);
112+
113+
void weave_yuv16_with_alpha_to_rgba16(const uint16_t *y_plane,
114+
uint32_t y_stride,
115+
const uint16_t *u_plane,
116+
uint32_t u_stride,
117+
const uint16_t *v_plane,
118+
uint32_t v_stride,
119+
const uint16_t *a_plane,
120+
uint32_t a_stride,
121+
uint16_t *rgba,
122+
uint32_t rgba_stride,
123+
uint32_t bit_depth,
124+
uint32_t width,
125+
uint32_t height,
126+
YuvRange range,
127+
YuvMatrix yuv_matrix,
128+
YuvType yuv_type);
129+
56130
void weave_scale_u8(const uint8_t *src,
57131
uint32_t src_stride,
58132
uint32_t width,
257 KB
Binary file not shown.
103 KB
Binary file not shown.
198 KB
Binary file not shown.
205 KB
Binary file not shown.

0 commit comments

Comments
 (0)