Android应用程序在物理设备上崩溃,但未在模拟器上崩溃:“包裹:dup在包裹::读取错误:错误:打开的文件太多” 根本原因可能是...

如何解决Android应用程序在物理设备上崩溃,但未在模拟器上崩溃:“包裹:dup在包裹::读取错误:错误:打开的文件太多” 根本原因可能是...

我正在尝试将旧手机变成网络安全摄像头,因为在所有这些骚乱期间,我所在地区的犯罪率急剧上升(而且我不想依靠别人的应用来控制对我私人时刻的访问) )。

我正在分块发送,因此摄像机将视频记录几秒钟,然后停止,将捕获文件的二进制编码到Base64中,然后通过POST请求将其拍摄到家庭服务器中,无休止的循环。服务器解包+解码+将其作为原始二进制“ MP4”保存到其自己的磁盘上(TODO:有趣的运动检测后处理)。

在目标手机的OS版本和屏幕尺寸(及周围)使用各种虚拟设备,所有这些都可以长时间使用。我用了60秒的块进行了15分钟以上的处理,再加上6秒的块进行了一个多小时的处理。我始终收到模拟器生成的愚蠢的虚拟房间视频到我的服务器上。

但是在运行Android 6.0.1的三星Galaxy S5梦想成为安全摄像机的情况下,通常会在应用程序崩溃之前发送2或3个视频...除非您将分辨率设置得过高,然后您才能运行变成另一种症状。

症状0:在区块末尾崩溃

E / Parcel:dup()在Parcel :: read中失败,我为1,fds [i]为-1,fd_count为2,错误:打开的文件太多

E /表面:dequeueBuffer:IGraphicBufferProducer :: requestBuffer失败:-22

W / Adreno-EGLSUB:DequeueBuffer:721:使本机缓冲区出队失败:参数无效,buffer = 0x0,handle = 0x0

W / Adreno-EGL::EGL_BAD_SURFACE

紧接着是第二个错误:

E / CameraDeviceGLThread-1:在GL渲染线程上收到异常:

java.lang.IllegalStateException: swapBuffers: EGL error: 0x300d

然后,最后,一旦块时间到了并且相机再次进行记录,就会发生最后的错误,导致整个应用崩溃:

I / CameraDeviceState:旧版摄像头服务转换为错误状态

E / AndroidRuntime:严重例外:CameraThread

Process: com.example.roselawncam,PID: 14639

android.hardware.camera2.CameraAccessException:摄像头设备遇到严重错误

症状1:由于对自己的好处太“高分辨率”而导致块中崩溃

这些警告清楚表明资源紧张会导致此症状。它们会在应用崩溃时发生,更高的分辨率会导致更快的崩溃。我给这些坏男孩打钟:

  • 1920x1080(30 FPS):5秒
  • 1280x720(30 FPS):9秒
  • 800x480(30 FPS):15秒

前后摄像头的时间相似。在较低的分辨率下,除非您增加了块时间,否则您将开始遇到“症状0”。无论如何:

W / Adreno-GSL::ioctl fd 28代码0xc01c0915(IOCTL_KGSL_MAP_USER_MEM)失败:errno 12 内存不足

W / Adreno-EGLSUB:SyncBackBuffer:3130:无法为fd = 281 offs = 0映射内存

E / Adreno-EGLSUB:SyncBackBuffer:3131:SyncBackBuffer:致命错误:(空)

A / Adreno-GSL:从功能SyncBackBuffer和第3131行退出com.example.roselawncam进程

A / libc:致命信号6(SIGABRT),在tid 19618(CameraDeviceGLT)中的代码-6

最后,相关的科特琳作品:

private fun createRecorder(surface: Surface) = MediaRecorder().apply {
        setAudioSource(MediaRecorder.AudioSource.MIC)
        setVideoSource(MediaRecorder.VideoSource.SURFACE)
        setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
        setOutputFile(outputFile.absolutePath)
        setVideoEncodingBitRate(RECORDER_VIDEO_BITRATE)
        if (args_fps > 0) setVideoFrameRate(args_fps)
        setVideoSize(args_width,args_height)
        setVideoEncoder(MediaRecorder.VideoEncoder.H264)
        setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
        setInputSurface(surface)
}

private fun recordIt(cameraManager: CameraManager,cameraThread: HandlerThread) {
    val cameraHandler = Handler(cameraThread.looper)
    val stateCallback: CameraDevice.StateCallback = object: CameraDevice.StateCallback() {
        override fun onOpened(camera: CameraDevice) {
            camera.createCaptureSession(
                listOf<Surface>(recorderSurface),object : CameraCaptureSession.StateCallback() {
                    override fun onConfigured(session: CameraCaptureSession) {
                        val recTimeSeconds = findViewById<TextView>(R.id.recTimeSeconds)
                        val chunkTimeMilliseconds = recTimeSeconds.text.toString().toLong() * 1000

                        // Boolean "stopREC" (e.g. "Stop Recording") is false at this point
                        while (!stopREC) {
                            // // // This loop should run forever,but crashes after a few times // // //
                            val recorder: MediaRecorder by lazy { createRecorder(recorderSurface) }
                            val recordRequest: CaptureRequest by lazy {
                                session.device.createCaptureRequest(CameraDevice.TEMPLATE_RECORD).apply {
                                    addTarget(recorderSurface)
                                    set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,Range(args_fps,args_fps))
                                }.build()
                            }
                            session.setRepeatingRequest(recordRequest,null,cameraHandler)
                            recorder.apply { prepare(); start() }
                            Thread.sleep(chunkTimeMilliseconds)
                            recorder.apply { stop(); release() }
    
                            // Send the video file across the network in JSON via POST request:
                            val params = HashMap<String,String>()
                            params["videodata"] = convertToBase64(outputFile)
                            val jsonObject = JSONObject(params as Map<*,*>)
                            val request = JsonObjectRequest(Request.Method.POST,url,jsonObject,null)
                            queue.add(request)
                            // // // End of loop that should've ran forever,but crashes occasionally instead  // // //
                        }
                        camera.close()
                    }
                    override fun onConfigureFailed(session: CameraCaptureSession) {}
                },cameraHandler
            )
        }
        override fun onDisconnected(camera: CameraDevice) { recorder.stop(); recorder.release() }
        override fun onError(camera: CameraDevice,error:Int) { camera.close() }
    }
    cameraManager.openCamera(args_cameraId,stateCallback,cameraHandler)
}

解决方法

我有一些建议:

  • 在需要file lock的地方强制使用同步函数,以便线程按顺序执行该代码块,以有组织的方式打开和关闭file stream,例如访问到文件。这样可以避免out of memoryfile already in use错误。

  • 是否可以不将文件编码为Base 64?字符串太大,请检查是否避免任何错误。

这是创建您自己的应用的好方法。

,

打开的文件太多

症状#0 的第一条错误消息是

E/Parcel: dup() failed in Parcel::read,i is 1,fds[i] is -1,fd_count is 2,error: Too many open files

来自Parcel.cpp

status_t err = NO_ERROR;
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
    fds[i] = dup(this->readFileDescriptor());
    if (fds[i] < 0) {
        err = BAD_VALUE;
        ALOGE("dup() failed in Parcel::read,i is %zu,fds[i] is %d,fd_count is %zu,error: %s",i,fds[i],fd_count,strerror(errno));
    }
}

它表明上述错误发生在

fds[i] = dup(this->readFileDescriptor());

我还搜索了Too many open files并发现了a similar question。它具有详细的错误日志和答案。两者都再次表示文件描述符

根本原因可能是...

params["videodata"] = convertToBase64(outputFile)

请检查convertToBase64()的实现。

根据thisthis,文件描述符可能会泄漏。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-