android-discuss
android-discuss copied to clipboard
Camera onPreviewFrame处理回调数据data,如何避免阻塞线程,并且不丢帧?
如题,通常我们在Camera回调函数onPreviewFrame(byte[] data, Camera camera)获取预览帧数据data,然后对data进行一些诸如转换、保存到文件的操作,以每秒15帧为例,帧与帧之间的间隔时间约为66.7ms,这意味着需要在66.7ms内处理完对data数据的转换、保存等工作,而文件写入操作有时候写入一帧的时间可能达到200ms,这样就会造成UI线程阻塞,onPreviewFrame回调次数也跟着减少,造成掉帧。
这样就得考虑用异步线程来对data进行转换、保存等操作了吧。 如果Camera预览配合addCallbackBuffer使用(假设add了三组buffer),那么onPreviewFrame回调的参数data就会是三组buffer中的一个(循环返回其一),如果异步处理data不及时依然会造成data被Camera重写的问题,这样应该会引发帧数据错乱,甚至损毁的问题吧。 请问针对此问题有什么好的解决方案?
承蒙 @start141 邀请。 不过之前实际开发中没有遇到过类似场景,这里说一点自己的想法,算是抛砖引玉。
- 首先使用三个 buffer 算是比较可取的,否则保存太多不仅处理不过来还容易造成 OOM;前段时间看 Framework 层的 Surface 系统就只用了两个,FrontBuffer(mPostedBuffer) 和 BackBuffer;
- 多个 buffer 需要实时处理可以试试 JDK 中的并发相关 API,比如
ExecutorService; - 刚刚想到了 zxing 项目,初看了下
PreviewCallback和AutoFocusManager代码,貌似使用的AsyncTask+Handler;
之前做的项目也遇到这个问题瓶颈,补上一个参考《Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用》,使用的方案也是AsyncTask,在图像的实时处理中,大部分算法都很难在短时间内完成,比如行人检测之类的,期待有更好的解决方案!
"然后对data进行一些诸如转换、保存到文件的操作,以每秒15帧为例,帧与帧之间的间隔时间约为66.7ms,这意味着需要在66.7ms内处理完对data数据的转换、保存等工作,而文件写入操作有时候写入一帧的时间可能达到200ms,这样就会造成UI线程阻塞,onPreviewFrame回调次数也跟着减少,造成掉帧。"
这个问题有解吗? 我也很好奇, camera录制视频时,需要编码并保存文件,是怎么做到可以在结束录制后,视频就被保存为文件的? 难道编码+保存会很快吗?特别是可以录制fps>=60的视频的时候,是如何解决的?
不在UI线程做
2015-12-04 14:47 GMT+08:00 Jin Ma [email protected]:
"然后对data进行一些诸如转换、保存到文件的操作,以每秒15帧为例,帧与帧之间的间隔时间约为66.7ms,这意味着需要在66.7ms内处理完对data数据的转换、保存等工作,而文件写入操作有时候写入一帧的时间可能达到200ms,这样就会造成UI线程阻塞,onPreviewFrame回调次数也跟着减少,造成掉帧。"
这个问题有解吗? 我也很好奇, camera录制视频时,需要编码并保存文件,是怎么做到可以在结束录制后,视频就被保存为文件的? 难道编码+保存会很快吗?特别是可以录制fps>=60的视频的时候,是如何解决的?
— Reply to this email directly or view it on GitHub https://github.com/android-cn/android-discuss/issues/144#issuecomment-161892658 .
@Qixingchen 不在UI线程里做是个必然条件. 有人说过他们录制视频,后写入文件,一帧就需要200ms. 按照fps=30来看,当你录制结束的时候,文件写入还远远未完成(还要保证buffer queue足够大). 但是看到咱们手机摄像头,录制视频结束后文件就生成了(你可以立马播放). 我很好奇这个是怎么做到的...
高清一样卡…或者你觉得快的, 放到低端机上, 也是卡….录制视频时候机器发烫你觉得是为什么..
Jin Ma [email protected]于2015年12月3日周四 下午11:29写道: @Qixingchen 不在UI线程里做是个必然条件. 有人说过他们录制视频,后写入文件,一帧就需要200ms. 按照fps=30来看,当你录制结束的时候, 文件写入还远远未完成(还要保证buffer queue足够大). 但是看到咱们手机摄像头,录制视频结束后文件就生成了( 你可以立马播放). 我很好奇这个是怎么做到的...
— Reply to this email directly or view it on GitHub .
这次我也遇到这个问题了,请求楼主现在找到方案了吗?
利用HandlerThead处理试试。使用 AsyncTask会因其默认的线性执行的特性,导致任务有时无法及时进入工作线程(doInBackground)处理。
这个问题最近也遇到了,使用buffer在人脸检测完成后,保存图片存在乱帧问题。个人觉得可以创建一个全局buffer,做数据处理时,先copy一份