grz*_*byk 4 android ffmpeg segmentation-fault android-ndk ontouchlistener
在使用FFmpeg和NDK时,我遇到了一个令人讨厌但众所周知的错误:
A/libc(9845): Fatal signal 11 (SIGSEGV), code 1, fault addr 0xa0a9f000 in tid 9921 (AsyncTask #4)
Run Code Online (Sandbox Code Playgroud)
UPDATE
几个小时后,我发现可能有两个问题来源.一个与多线程有关.我查了一下,然后修好了.现在,只有在视频播放(ndk)打开时,应用程序才会崩溃.
我在触摸事件中放了一个"计数器"
surfaceSterowanieKamera.setOnTouchListener(new View.OnTouchListener() {
int counter = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
if ((event.getAction() == MotionEvent.ACTION_MOVE)){
Log.i(TAG, "counter = " + counter);
//cameraMover.setPanTilt(some parameters);
counter++;
}
Run Code Online (Sandbox Code Playgroud)
我开始逐个禁用其他应用功能,但没有视频.我发现,每减少一个功能,压缩需要更长的时间 - 计数器达到更高的值.在关闭视频播放和触摸界面(cameraMover.setPanTilt()
注释掉)之外的所有内容后,应用程序通常在计数器介于1600 - 1700之间时会崩溃.
在这种情况下,logcat显示上述错误和GC相关信息.对我而言,似乎GC正在搞乱ndk.
01-23 12:27:13.163: I/Display Activity(20633): n = 1649
01-23 12:27:13.178: I/art(20633): Background sticky concurrent mark sweep GC freed 158376(6MB) AllocSpace objects, 1(3MB) LOS objects, 17% free, 36MB/44MB, paused 689us total 140.284ms
01-23 12:27:13.169: A/libc(20633): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9bd6ec0c in tid 20734 (AsyncTask #3)
Run Code Online (Sandbox Code Playgroud)
为什么GC导致ndk部分应用程序出现问题?
原始问题
我在做什么?
我正在开发一个应用程序,从网络摄像头流式传输实时视频,并使用户能够平移和倾斜远程摄像头.我正在使用用NDK构建的FFmpeg库来实现流畅的播放,几乎没有延迟.
我正在使用FFMpeg库连接到视频流.然后ndk部分创建位图,对SurfaceView videoSurfaceView
位于android活动(java部分)中的对象进行图像处理和渲染帧.
为了移动网络摄像头,我创建了一个单独的类 - public class CameraMover implements Runnable{/**/}
.此类是一个单独的线程,通过套接字与远程摄像头连接,并管理仅通过云台移动连接的任务.
接下来在主要活动中我创建了一个触摸监听器
videoSurfaceView.setOnTouchListener(new View.OnTouchListener() {/**/
cameraMover.setPanTilt(some parameters);
/**/}
Run Code Online (Sandbox Code Playgroud)
它读取用户的手指移动并向摄像机发送命令.
所有任务 - 移动相机,触摸界面和视频播放都可以正常工作,当其他人被禁用时,即当我禁用移动相机的可能性时,我可以观看视频流和注册触摸事件直到时间结束(或电池)至少).仅当任务配置为同时工作时才会出现此问题.
我无法找到重现问题的步骤.它只是发生,但只有在用户触摸屏幕移动相机后.它可以在第一次交互后15秒,但有时需要10分钟或更长时间才能崩溃.通常它是一分钟左右的东西.
我做了什么来解决它?
videoSurfaceView
并分配了触摸监听器.这一切都以同样的错误结束.错误的类型
几乎每次错误看起来像这样:
A/libc(11528): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9aa9f00c in tid 11637 (AsyncTask #4)
Run Code Online (Sandbox Code Playgroud)
两个错误之间的差异是libc,addr number和tid number之后的数字.很少AsyncTask数量变化 - 我收到了#1几次,但我无法重现它.
题
我怎样才能避免这个错误?它的来源是什么?
您引用的错误消息libc: Fatal signal 11 (SIGSEGV)
并没有说明实际发生的事情 - 这只是说某些东西试图错误地访问内存(读取或写入).由于这是一个C api,它可能只是任何错误 - 使用指针,使用不再有效的指针,将太多数据写入太小的缓冲区等.
所以遗憾的是,这并没有提供太多线索 - 如果没有看到相关的C代码,就不可能说出导致这种情况的原因.
通常,设备日志还包含某种调试信息,这些信息至少可以提供错误发生位置的模糊提示 - 请参阅最简单的方法来调试本机库中的崩溃,由Android应用程序链接?举个例子.这篇文章还包含有关启用CheckJNI以获得有关滥用JNI函数的更好调试信息的提示,这可能是导致问题的原因之一.NDK的还包含了工具ndk-stack
和ndk-gdb
可用于获取有关崩溃的发生位置更精确的信息.
请注意,即使您获得了崩溃发生位置的精确定位,也可能无法直接指向代码中的错误位置.
在这种情况下,当你说它似乎是GC导致它时,听起来像是你通过JNI滥用java对象 - 好像你保持对java对象的引用而不通过JNI正确保存引用.当GC运行时,它可以移动分配的数据,假设没有人保持直接指向它.
请参阅http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html以获取有关它可能的更多提示.