ffmpeg-kit
ffmpeg-kit copied to clipboard
Low level crash on Android 12 with targetSdk 31
Description Low level crash when creating videos from frames at specific resolution.
This occurs with the combination of Android 12 ARM devices, compileSdk and targetSdk 31. Most resolutions are fine. For example it crashes at 792x1568. It doesn't crash at 720x1280.
If the complieSdk and targetSdk are set to 30 it doesn't crash. It also doesn’t crash if it’s run on older Android (for example Android 10 or 11) devices even with compileSdk and targetSdk 31. It also doesn't crash when running on x86-64 Android 12 emulator.
It does crash on Google Pixel 6, Samsung Galaxy S20, Samsung Galaxy S20 Ultra, Samsung Fold 2 and Xiaomi Mi 11 Lite 5G. All of them are running Android 12.
Expected behavior Should finish the ffmpeg process without low level crash.
Current behavior Crashes the whole app without the ability to catch the error.
To Reproduce
plugins {
id 'com.android.application'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.zombodroid.ffmepgskelet"
minSdk 21
targetSdk 31
versionCode 10000
versionName "1.0000"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.arthenica:ffmpeg-kit-full-gpl:4.5.1-1.LTS'
}
package com.zombodroid.ffmepgskelet;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import com.arthenica.ffmpegkit.FFmpegKit;
import com.arthenica.ffmpegkit.FFmpegSession;
import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Locale;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
private static final String LOG_TAG = "MainActivity";
private Random rGen;
private Paint paint;
private File cacheFolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initVars();
initView();
}
private void initVars() {
rGen = new Random();
paint = new Paint();
paint.setColor(Color.WHITE);
}
private void initView(){
findViewById(R.id.buttonMakeVideo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
long timeNow = System.currentTimeMillis();
cacheFolder = new File(getCacheDir() + "/" + timeNow);
cacheFolder.mkdirs();
int frameCount = 100;
int imgW = 792;
int imgH = 1568;
new Thread(new Runnable() {
@Override
public void run() {
makeFrames(frameCount, imgW, imgH);
makeVideoFromFrames();
}
}).start();
}
});
}
//makes 100 frames and stores them in storage
private void makeFrames(int frameCount, int imgW,int imgH) {
for (int i=1;i<=frameCount;i++){
String fileName = "frame-" + String.format(Locale.ENGLISH,"%03d", i) + ".jpg";
Bitmap bitmap = getRandomImage(imgW, imgH);
try {
FileOutputStream fos = new FileOutputStream(new File(cacheFolder, fileName));
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
Log.i(LOG_TAG, "saved file: " + fileName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//crates a raddom black and white image
private Bitmap getRandomImage(int imgW, int imgH){
Bitmap bitmap = Bitmap.createBitmap(imgW, imgH, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
int whitePartX = rGen.nextInt(imgW - 1);
int whitePartY = rGen.nextInt(imgH - 1);
canvas.drawRect(0,0,whitePartX, whitePartY, paint);
return bitmap;
}
private void makeVideoFromFrames() {
File videoFile = new File(cacheFolder, "videoTest.mp4");
String framePath = cacheFolder.getAbsolutePath() + "/frame-%3d.jpg";
String videoPath = videoFile.getAbsolutePath();
String cmd = "-framerate 20 -i " + framePath + " -c:v libx264 \"" + videoPath + "\"";
Log.i(LOG_TAG, "Ffmpeg cmd: " + cmd);
FFmpegKit.executeAsync(cmd, new FFmpegSessionCompleteCallback() {
@Override
public void apply(FFmpegSession session) {
Log.i(LOG_TAG, "Ffmpeg finished" );
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Ffmpeg finished", Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
You can also download this sample project and run it here
Logs
2022-04-13 13:36:48.219 14631-14700/com.zombodroid.ffmepgskelet A/libc: Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0xb4000077bf8c1000 in tid 14700 (pool-2-thread-1), pid 14631 (id.ffmepgskelet) 2022-04-13 13:36:48.290 14703-14703/? I/crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstoneProto 2022-04-13 13:36:48.290 562-562/? I/tombstoned: received crash request for pid 14700 2022-04-13 13:36:48.291 14703-14703/? I/crash_dump64: performing dump of process 14631 (target tid = 14700) 2022-04-13 13:36:48.296 14703-14703/? E/DEBUG: failed to read /proc/uptime: Permission denied 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: Build fingerprint: 'google/oriole/oriole:12/SP2A.220305.013.A3/8229987:user/release-keys' 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: Revision: 'MP1.0' 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: ABI: 'arm64' 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: Timestamp: 2022-04-13 13:36:48.296652388+0200 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: Process uptime: 0s 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: Cmdline: com.zombodroid.ffmepgskelet 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: pid: 14631, tid: 14700, name: pool-2-thread-1 >>> com.zombodroid.ffmepgskelet <<< 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: uid: 10245 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: tagged_addr_ctrl: 0000000000000001 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0xb4000077bf8c1000 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: x0 b4000079021a0770 x1 b4000077bf8792b4 x2 b4000077bf87b904 x3 b4000077bf887894 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: x4 b4000077bf8c0ff4 x5 00000077ecbf52dc x6 00000000fffffffa x7 0000000000000032 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: x8 0000000000000061 x9 b4000077bf8be9b0 x10 0000000000000032 x11 00000077f75556c0 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: x12 b4000077bf8792b0 x13 0000000000000061 x14 0000000000007fff x15 0000000000000032 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: x16 b4000077bf887824 x17 b4000077bf82ef28 x18 00000077cb54e000 x19 0000000000000028 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: x20 b400007b2d6c5e80 x21 00000077ecbf64f8 x22 b4000077bf885240 x23 b400007b2d6cbdd0 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: x24 0000000000000028 x25 b4000077bf887824 x26 0000000000000028 x27 b4000077bf879244 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: x28 b4000079021a0710 x29 00000000000012f2 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: lr 00000077f7516024 sp 00000077ecbf5290 pc 00000077f75556d4 pst 0000000080001000 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: backtrace: 2022-04-13 13:36:48.420 14703-14703/? A/DEBUG: #00 pc 000000000074b6d4 /data/app/~~xbYVUNVUZrWxWt3__-blfA==/com.zombodroid.ffmepgskelet-vGwrgb9E-5BvgR_hJuotmw==/lib/arm64/libavcodec.so 2022-04-13 13:36:48.430 562-562/? E/tombstoned: Tombstone written to: tombstone_28
Environment
- Platform:
Android
- Architecture:
arm
- Version:
v4.5
/v4.5.LTS
I see that there is a problem there. But I'm not sure why it happens. This issue must be debugged.
I spent some time on this today. I extracted the following native stack trace.
x264_8_mbtree_propagate_cost_neon => libavcodec.so(yuv4enc.c:?)
macroblock_tree_propagate => libavcodec.so(src/x264/encoder/slicetype.c:1072)
macroblock_tree => libavcodec.so(src/x264/encoder/slicetype.c:1170)
x264_8_slicetype_analyse => libavcodec.so(src/x264/encoder/slicetype.c:1678)
x264_8_lookahead_get_frames => libavcodec.so(src/x264/encoder/lookahead.c:241)
x264_8_encoder_encode => libavcodec.so(src/x264/encoder/encoder.c:3428)
x264_encoder_encode => libavcodec.so(src/x264/encoder/api.c:165)
X264_frame => libavcodec.so(src/ffmpeg/libavcodec/libx264.c:496)
encode_simple_internal => libavcodec.so(src/ffmpeg/libavcodec/encode.c:211)
avcodec_send_frame => libavcodec.so(src/ffmpeg/libavcodec/encode.c:378)
do_video_out => libffmpegkit.so (fftools_ffmpeg.c:1478)
reap_filters => libffmpegkit.so (fftools_ffmpeg.c:1673)
transcode_step => libffmpegkit.so (fftools_ffmpeg.c:4962)
ffmpeg_execute => libffmpegkit.so (fftools_ffmpeg.c:5714)
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegExecute => libffmpegkit.so (ffmpegkit.c:814)
Android documentation says that SEGV_ACCERR
we see in the logs is raised when an Execute-only memory violation
occurs. But in this issue, we don't see the cause given in the Diagnosing Native Crashes page. So, we can't say that there is a Execute-only memory violation
here.
My guess is that this is a bug or an incompatibility issue coming from ffmpeg
and x264
. Looking at the symptoms and the logs, I think one of these two libraries may have problems about ARM Memory Tagging Extension support explained in Tagged Pointers page. I'm not % 100 sure about this. So, I'll keep an eye on similar incidents reported for other Android apps.
I got same issue here
E/DEBUG: failed to read /proc/uptime: Permission denied A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** A/DEBUG: Build fingerprint: 'google/sargo/sargo:12/SQ1A.211205.008/7888514:user/release-keys' A/DEBUG: Revision: 'MP1.0' A/DEBUG: ABI: 'arm64' A/DEBUG: Timestamp: 2022-04-23 16:03:22.399615178+0530 A/DEBUG: Process uptime: 0s A/DEBUG: Cmdline: qr.qrgenerator A/DEBUG: pid: 30643, tid: 31909, name: pool-6-thread-2 >>> qr.qrgenerator <<< A/DEBUG: uid: 10212 A/DEBUG: signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x6fe0b79000 A/DEBUG: x0 000000712f18fbc0 x1 0000006fe0b5c360 x2 0000006fe0b5e0b4 x3 0000006fe0b639f4 A/DEBUG: x4 0000006fe0b78ff4 x5 0000006ff509a2dc x6 00000000fffffffa x7 0000000000000032 A/DEBUG: x8 0000000000000025 x9 0000006fe0b78120 x10 0000000000000032 x11 00000070165caffc A/DEBUG: x12 0000006fe0b5d1d0 x13 0000000000000025 x14 0000000000007fff x15 0000000000000032 A/DEBUG: x16 0000006fe0b63984 x17 0000006fe0b4f258 x18 0000006fee4ca000 x19 0000000000000027 A/DEBUG: x20 000000734f633e80 x21 0000006ff509b4f8 x22 0000006fe0b62b10 x23 000000734f639dd0 A/DEBUG: x24 0000000000000027 x25 0000006fe0b63984 x26 0000000000000028 x27 0000006fe0b5c2f0 A/DEBUG: x28 000000712f18fb60 x29 000000000000073a A/DEBUG: lr 000000701658b960 sp 0000006ff509a290 pc 00000070165cb010 pst 0000000080000000 A/DEBUG: backtrace: A/DEBUG: #00 pc 0000000000359010 /data/app/~~s6y-vHk-TLOk_RoUfYHyeg==/qr.qrgenerator-Kv9Ehh0rB7yPJ_XfiY_rQQ==/lib/arm64/libavcodec.so
In less than 2 week Google is going to enforce targetSdk 31 for all new apps. In November for all app updates. https://developer.android.com/google/play/requirements/target-sdk
Can we expect to have this issue resolved any time soon?
Yeah, I'm working on the new release these days. I can give an update as soon as I test this.
My tests show that this issue is still there when we use the latest ffmpeg
and x264
source code.
Created ffmpeg ticket #9894 on upstream ffmpeg
project and x264 issue #53 on x264
. Hope ffmpeg
or x264
developers can find the root cause of this issue.
This issue is fixed in x264
. development
branch is updated to depend on the updated x264
version.
That's great to hear. Will try to check it out this week.
Is there a way of including the development branch build as an Android dependency? To replace this line:
implementation 'com.arthenica:ffmpeg-kit-full-gpl:4.5.1-1.LTS'
We don't have experience building Android native JNI projects.
Sorry, about the closed/reopened status. Clicked the wrong button when posting the comment.
You can try implementation 'com.arthenica:ffmpeg-kit-full-gpl:5.1.LTS'
that I use for testing. It is available in the following staging repository.
repositories {
maven {
url 'https://oss.sonatype.org/content/repositories/comarthenica-1020'
}
}
How do you use the development branch + full-gpl in flutter without having conflicting sources?
in flutter pubspec.yaml - don't think i can specify full_gpl
here.
ffmpeg_kit_flutter:
git:
url: https://github.com/tanersener/ffmpeg-kit/
path: flutter/flutter
branch: development
I tried using
implementation 'com.arthenica:ffmpeg-kit-full-gpl:5.1.LTS
but that conflicts with the com.arthenica:ffmpeg-kit-https:4.5.1-1
getting pulled from the pubspec
I'm getting this crash on Android 12 + 13 using libx265. wanted to see if development branch would help.
Appreciate all your work on this
Our initial testing shows this bug as fixed, at least at the 792x1568 resolution. Will do more testing next week at different output resolutions to confirm.
Do you have any roadmap on when this 'com.arthenica:ffmpeg-kit-full-gpl:5.1.LTS'
will go into the main branch?
We are hesitant to use your staging repository in our production builds.
It will be out this weekend if everything goes well. If not, next weekend.