Skip to content

Commit

Permalink
android_jni: Set threads to 2 instead of CPU count
Browse files Browse the repository at this point in the history
Empirically, on Android devices with more than 1 core, it is
almost always better to use 2 threads than to use
number_of_cpu_cores threads.

Update the public java API function documentation to reflect this
change.

The new behavior is:
* negative values map to number of cpu cores.
* zero maps to 1 or 2 depending on single core or multi core devices.
* value >=0 maps to value.

This change ensures that users who use the library via JNI take the
optimal path when using the default value of 0.
  • Loading branch information
vigneshvg committed Oct 9, 2024
1 parent df2f379 commit a12f203
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,11 @@ public static boolean decode(ByteBuffer encoded, int length, Bitmap bitmap) {
* @param bitmap The decoded pixels will be copied into the bitmap.
* If the bitmap dimensions do not match the decoded image's dimensions,
* then the decoded image will be scaled to match the bitmap's dimensions.
* @param threads Number of threads to be used for the AVIF decode. Zero means use number of CPU
* cores as the thread count. Negative values are invalid. When this value is > 0, it is
* simply mapped to the maxThreads parameter in libavif. For more details, see the
* documentation for maxThreads variable in avif.h.
* @return true on success and false on failure. A few possible reasons for failure are: 1) Input
* was not valid AVIF. 2) Negative value was passed for the threads parameter.
* @param threads Number of threads to be used for the AVIF decode. Zero means use the library
* determined optimal value as the thread count. Negative values mean use the number of CPU
* cores as the thread count. For more details, see the documentation for maxThreads variable
* in avif.h.
* @return true on success and false on failure.
*/
public static native boolean decode(ByteBuffer encoded, int length, Bitmap bitmap, int threads);

Expand Down
19 changes: 10 additions & 9 deletions android_jni/avifandroidjni/src/main/jni/libavif_jni.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cpu-features.h>
#include <jni.h>

#include <algorithm>
#include <cstdio>
#include <memory>
#include <new>
Expand Down Expand Up @@ -210,7 +211,15 @@ avifResult DecodeNthImage(JNIEnv* const env, AvifDecoderWrapper* const decoder,
}

int getThreadCount(int threads) {
return (threads == 0) ? android_getCpuCount() : threads;
if (threads < 0) {
return android_getCpuCount();
}
if (threads == 0) {
// Empirically, on Android devices with more than 1 core, decoding with 2
// threads is almost always better than using as many threads as CPU cores.
return std::min(android_getCpuCount(), 2);
}
return threads;
}

// Checks if there is a pending JNI exception that will be thrown when the
Expand Down Expand Up @@ -286,10 +295,6 @@ FUNC(jboolean, getInfo, jobject encoded, int length, jobject info) {
FUNC(jboolean, decode, jobject encoded, int length, jobject bitmap,
jint threads) {
IGNORE_UNUSED_JNI_PARAMETERS;
if (threads < 0) {
LOGE("Invalid value for threads (%d).", threads);
return false;
}
const uint8_t* const buffer =
static_cast<const uint8_t*>(env->GetDirectBufferAddress(encoded));
AvifDecoderWrapper decoder;
Expand All @@ -301,10 +306,6 @@ FUNC(jboolean, decode, jobject encoded, int length, jobject bitmap,
}

FUNC(jlong, createDecoder, jobject encoded, jint length, jint threads) {
if (threads < 0) {
LOGE("Invalid value for threads (%d).", threads);
return 0;
}
const uint8_t* const buffer =
static_cast<const uint8_t*>(env->GetDirectBufferAddress(encoded));
std::unique_ptr<AvifDecoderWrapper> decoder(new (std::nothrow)
Expand Down

0 comments on commit a12f203

Please sign in to comment.