#10140: swscale crash in Android starting from API31
-------------------------------------+-------------------------------------
Reporter: fabienst | Type: defect
Status: new | Priority: normal
Component: | Version:
undetermined | unspecified
Keywords: swscale | Blocked By:
Blocking: | Reproduced by developer: 0
Analyzed by developer: 0 |
-------------------------------------+-------------------------------------
I have a crash in my call to sw_scale since Android API 31. I doesn't
crash for all inputs, but for now only on the same given picture. It works
fine with API 30.
I'm calling sw_scale from a native function through JNI which is calling
from java.
The input picture is a "Bitmap" object.
The problem still exists in the present snapshot of ffmpeg (2023-01-15).
BTW, this LDFLAGS is missing to build for Android: {{{-lnativewindow}}}
If I run the same command from ffmpeg but with directly the file as input,
I don't have a crash, but the input is then a jpeg, while programatically
it's a bitmap object.
{{{
LD_LIBRARY_PATH=. ./ffmpeg -i
/storage/emulated/0/DCIM/test_pics/invalid/image01088.jpg -vf scale=160x45
-sws_flags print_info -sws_flags lanczos -loglevel trace a.jpg
}}}
I enabled logging in my program as much as I could.
You will find attached the log for the run on a device running android 11
(=API30) and the log for the run on a device with Android 12 (API31).
These were made within the Android emulator.
Crash is reported as:
{{{
A/libc: Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr
0x7e936e915000 in tid 9755 (ServiceStartArg), pid 9722 (adder.app.debug)
}}}
Crash is at this line inside swscale() function:
{{{
desc[i].process(c, &desc[i], firstCPosY, lastCPosY - firstCPosY + 1);
}}}
I would like to provide the input picture but I don't know how to make a
file out of this bitmap object. However, I attached the jpeg just in case.
I also attached the material that the android emulator collects to produce
bug reports.
The java code: Algo is LANCZOS, but it fails also with others IIRC
{{{
public static Bitmap rescale(Bitmap src, int dstWidth, int dstHeight,
AlgoParametrized1 algo, double p0) {
int final_algo = algo.flag;
if (MainApplication.enableLog)
final_algo |= Algo.SWS_PRINT_INFO.flag;
return native_rescale(src, Bitmap.createBitmap(dstWidth,
dstHeight, src.getConfig()),
final_algo | Algo.SWS_PRINT_INFO.flag, p0, 0.0);
}
}}}
The C code:
{{{
/* SPDX-License-Identifier: (BSD-2-Clause or GPL-2.0-only) */
// Adapted for Exif Thumbnail Adder
// From: https://raw.githubusercontent.com/ser-
gik/smoothrescale/master/smoothrescale/src/main/jni/on_load.c
#include <stddef.h>
#include <stdint.h>
#include <jni.h>
#include <android/log.h>
#include <android/bitmap.h>
#include <libswscale/swscale.h>
#include <libavutil/pixfmt.h>
#include <libavutil/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,
"schokoladenbrown", __VA_ARGS__)
struct bitmap {
jobject jbitmap;
AndroidBitmapInfo info;
uint8_t *buffer;
};
static int lock_bitmap(JNIEnv *env, struct bitmap *bm) {
int res = AndroidBitmap_getInfo(env, bm->jbitmap, &bm->info);
if(ANDROID_BITMAP_RESULT_SUCCESS != res) return res;
else return AndroidBitmap_lockPixels(env, bm->jbitmap, (void
**)&bm->buffer);
}
static int unlock_bitmap(JNIEnv *env, struct bitmap *bm) {
const static struct bitmap null_bm;
int res = AndroidBitmap_unlockPixels(env, bm->jbitmap);
*bm = null_bm;
return res;
}
static inline enum AVPixelFormat pix_fmt(enum AndroidBitmapFormat fmt) {
/* bitmap formats directly correspond to SkColorType values */
switch (fmt) {
case ANDROID_BITMAP_FORMAT_RGBA_8888:
/*
* kN32_SkColorType
* Actually it may be one of kBGRA_8888_SkColorType or
kRGBA_8888_SkColorType
* and may be configured at build time. Seems like Android
uses RGBA order.
*/
return AV_PIX_FMT_RGBA;;
case ANDROID_BITMAP_FORMAT_RGB_565:
/*
* kRGB_565_SkColorType
* This one is packed in native endianness
*/
return AV_PIX_FMT_RGB565;
case ANDROID_BITMAP_FORMAT_A_8:
/*
* kAlpha_8_SkColorType
* There is no appropriate AV_PIX_FMT_*
*/
/* fall through */
default:
return AV_PIX_FMT_NONE;
}
}
static jobject JNICALL native_rescale_impl(JNIEnv *env, jclass clazz,
jobject srcBitmap, jobject dstBitmap, jint sws_algo, jdouble p0,
jdouble p1) {
struct bitmap src = { .jbitmap = srcBitmap };
struct bitmap dst = { .jbitmap = dstBitmap };
jobject ret = NULL;
// LOGI("algo %x %lf %lf", sws_algo, p0, p1);
if(ANDROID_BITMAP_RESULT_SUCCESS == lock_bitmap(env, &src)
&& ANDROID_BITMAP_RESULT_SUCCESS == lock_bitmap(env, &dst)) {
const uint8_t *src_planes[] = { src.buffer };
const int src_strides[] = { src.info.stride };
uint8_t *dst_planes[] = { dst.buffer };
const int dst_strides[] = { dst.info.stride };
const double params[] = { p0, p1 };
struct SwsContext *ctx;
LOGI("%i", __LINE__);
LOGI("src %i", src.info.format);
LOGI("srcwidth %i", src.info.width);
LOGI("srcheight %i", src.info.height);
LOGI("dst %i", dst.info.format);
LOGI("dst width %i", dst.info.width);
LOGI("dst height %i", dst.info.height);
LOGI("sws_algo %i", sws_algo);
// Set loglevel (uncomment to debug ffmpeg issues)
av_log_set_flags(AV_LOG_PRINT_LEVEL | AV_LOG_SKIP_REPEATED);
av_log_set_level(AV_LOG_TRACE);
ctx = sws_getContext(src.info.width, src.info.height,
pix_fmt(src.info.format),
dst.info.width, dst.info.height,
pix_fmt(dst.info.format),
sws_algo, NULL, NULL, params);
LOGI("%i", __LINE__);
if(ctx) {
LOGI("%i", __LINE__);
int res = sws_scale(ctx, src_planes, src_strides, 0,
src.info.height, dst_planes, dst_strides);
LOGI("%i", __LINE__);
sws_freeContext(ctx);
LOGI("%i", __LINE__);
if(res > 0) {
ret = dstBitmap;
}
}
}
LOGI("%i", __LINE__);
unlock_bitmap(env, &src);
LOGI("%i", __LINE__);
unlock_bitmap(env, &dst);
return ret;
}
static const char *g_rescaler_java_class = "com/schokoladenbrown/Smooth";
static const JNINativeMethod g_native_methods[] = {
{"native_rescale",
"(Landroid/graphics/Bitmap;Landroid/graphics/Bitmap;IDD)Landroid/graphics/Bitmap;",
native_rescale_impl},
};
jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
JNIEnv *env = NULL;
jclass cls;
(*jvm)->AttachCurrentThread(jvm, &env, NULL);
cls = (*env)->FindClass(env, g_rescaler_java_class);
(*env)->RegisterNatives(env, cls, g_native_methods, sizeof
g_native_methods / sizeof g_native_methods[0]);
return JNI_VERSION_1_2;
}
}}}
--
Ticket URL: <https://trac.ffmpeg.org/ticket/10140>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker_______________________________________________
FFmpeg-trac mailing list
[email protected]
https://ffmpeg.org/mailman/listinfo/ffmpeg-trac
To unsubscribe, visit link above, or email
[email protected] with subject "unsubscribe".