息屏录像模块

基于以下原理, 做出了完整的后头录像锁屏app.不同于其它监控软件的伪后台(伪装窗口运行),此模块完全后台运行,即使锁屏状态也能监测和录像. 支持高清录像/录音/选择摄像头.

锁屏app介绍

当前功能有:
移动侦测录像. 此软件可以侦测摄像头范围内画面.当发生画面变化时自动开始录像,当动作停止一分钟后自动停止录像并保存;
晃动手机启动录像;

可定制做 脸部识别侦测录像.侦测到人脸时自动开始录像. 用usb红外摄像头作为输入源(已测试部分设备可行), 录像后自动上传到网盘, 多路摄像头录像. 这些功能demo做过, 但是没时间集成到这个应用.

使用场景:
可用于室内防盗/宠物记录/隐蔽拍摄等.
后台录像已做成 androidStudio 模块. 直接调用使用. 需要此模块请私信或联系邮箱 ilotuo@163.com 咨询.

演示视频

http://v.youku.com/v_show/id_XMTY3NTA1NDk4MA==.html?spm=a2hzp.8253869.0.0.4C43Bp&from=y1.7-2

整体框架原理

模块录像时一共有3个线程;

  1. preview 线程一直运行, 从camera获得数据到surfacetexture;
  2. 一个控制线程 Server,也是一直运行, 控制相机初始化,回调,录像源选择,启动录像;
  3. 编码线程实现从surface编码;

预览线程要创建一个”离屏egl surface";
编码线程要从mediacodec返回的surface创建egl surface;
开始录像和停止录像的时候,要让渲染环境在两个线程间互相切换。

离屏渲染

preview 线程做的事情是将Camera预览的内容渲染到一个离屏渲染环境. 如何创建一个离屏渲染环境?

  1. 创建一个offscreen egl surface;
  2. 获得默认display 设备和缓存等;
  3. makeCurrent,使用该surface和egl display设备,缓存等创建egl上下文,这是个共享上下文,可以在多个渲染线程使用;
  4. opengl初始化,纹理初始化,surfacetexture初始化,得到对应surface。

关于egl是什么见引用文章。

Android从Surface编码原理

这是api 18之后的功能。下面尝试把手机摄像头preview渲染到Input Surface.然后对该Surface编码.
首先该Surface由MediaCodec创建:

mSurface = mMediaCodec.createInputSurface(); // API >= 18

然后手动为该Surface初始化EGL后,渲染GL画面,编码。

add on 06/30/2016 SurfaceEncode Example .

编码输出
先看编码是怎么输出的.典型的MediaCodec Buffer编码,dequeueOutputBuffer的流水线顺序是这样:
1: changeFormat .
2: deque sps,pps buffer . BufferInfo 的flags被置位为:BUFFER_FLAG_CODEC_CONFIG.(如果是编码为h264,此时应写入h264文件)
3: IFrame (2+3 = IDR Frame)
4: many pFrame …

但是当使用InputSurface时,第二步被跳过,也就是没有BUFFER_FLAG_CODEC_CONFIG buffer,此时应该手动取sps和pps :

                    ByteBuffer sps = newFormat.getByteBuffer("csd-0");ByteBuffer pps = newFormat.getByteBuffer("csd-1");

如果是H264裸流要先把这两个buffer写到文件头或推流.
详见SufraceEncoder.md drainAllEncoderMuxer函数.

初始化EGL
本例以手机摄像头录像为例. 下面的代码来自SufraceEncoder.md(上一节有开源链接). 在preview渲染线程增加录像线程:

                mSurfaceEncoder = new SurfaceEncoder(thread.mVideoSource.mCols,thread.mVideoSource.mRows);Surface sur = mSurfaceEncoder.getInputSurface();mRendererHolder.setRecordingSurface(sur);

其中 mRendererHolder为preivew主线程.
seRecordingSSurface函数:

 public void setRecordingSurface(final Surface surface){RecordSurfaceRenderHandler rh = RecordSurfaceRenderHandler.createHandler();rh.setEglContext(mMasterEgl.getContext(), mTexId, surface, true);mClients.add(rh);}

RecordSurfaceRenderHandler 完成创建录制线程,为Surafce初始化EGL,在帧更新回调时切换EGL Context,并绘制到Surface.
源码 RecordSurfaceRenderHandler.md
关于EGL初始化,首先了解下EGL是什么,我这里看过两篇文章讲的比较好. 引用文章[1]和[2]

第一篇讲EGL原理,本质.第二篇将EGL应用.
通过以上文章我们知道,我们将要共享一块纹理, 那么EGL context 是唯一. 任何EGL Surface 渲染前都要和这个Context 绑定.使成为渲染目标.如果你的渲染主线程来自GLSurfaceView ,那么要先获得它的EGLContext, 我还没有实践过,也许可以参考这个提问:android - How can GLSurfaceView use my EGLDisplay, EGLContext and eglSurface? - Stack Overflow
handleSetEglContext 函数为surface初始化EGL环境,EGLBase在grafika工程有,过程和原理结合源码参考上面的#2链接.可以认为其所做的都是为makeCurrent(切换渲染对象)时做准备. EGLBase#makeCurrent实现就调用了一句:

 EGL14.eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)

将共享Context和我们的Surface绑定在一起.

Draw

把编码线程当成主线程的一个client,在主渲染线程帧回调时,向编码线程发送消息:

handler.sendMessage(handler.obtainMessage(MSG_RENDER_DRAW2, (int) (timestamp >> 32), (int) timestamp,mTxtMat));

编码线程的处理: GLDrawer2D 负责编译shader 和调用GLES接口进行渲染,以及Surface swap交换帧缓存.每次更新自动给MediaCodec输入帧数据.RencordSurfaceRenderHandler#handleFrameAvailable 完成渲染和drain编码:

     private void handleFrameAvailable(int tex_id,float[] transform, long timestampNanos) {Log.v(TAG,"handleFrameAvailable #0");SurfaceEncoder mVideoEncoder = SurfaceEncoder.getInstance();if(mVideoEncoder==null || !mVideoEncoder.isRecording())return;Log.d(TAG, "handleDrain: #3");mVideoEncoder.drainAllEncoderMuxer(false);mDrawer.draw(tex_id, transform);mTargetSurface.setPresentationTime(timestampNanos);mTargetSurface.swap();Log.v(TAG,"handleFrameAvailable #1");}

mVideoEncoder.drainAllEncoderMuxer 编码输出前面讲过了,和BufferInput差不多,去掉Buffer输入和注意sps和pps保存即可.
录制线程的帧回调只是多了mTargetSurface.swap().其作用就是调用GL14.eglSwapBuffers(mEglDisplay, surface) 将画到EglDisplay上的缓存换到Surface的帧缓存,录制线程的绘制.

小结

如何从surface编码?

  1. mediacodec 创建inputsurface;
  2. 设置一个录像线程,但是要求使用同一个shard_context,使用input surface创建EGLSruface;
  3. 初始化openGL,shader等;
  4. makeCurrent, 把当前(录像线程)设置为渲染线程;
  5. 渲染线程只更新surfaceTexture,不画出来,把SurfaceTexture传给录像线程;

参考文档

#1 科学网—EGL资源的数据共享应用和底层驱动实现 - 郭叶军的博文
#2 学习OpenGL-ES: 2 - EGL解析 - kiffa - 博客园

saki4510t/UVCCamera
google/grafika: Grafika test app

MediaCodec 从Surface编码及android锁屏录像和后台录像实现相关推荐

  1. android锁屏显示应用程序,今日应用:微软又给 Android 做了一款锁屏应用

    微软又做了一款 Android 锁屏应用,质量还不错.如果你已经设置了锁屏,Picturesque可能让你再解锁一次你真的需要在锁屏就处理这么多任务吗? 微软又来给 Android 提供应用了,他们昨 ...

  2. android 锁屏音量,Android锁屏状态获取音量按键事件

    Android系统没有提供音量按键的广播,而Activity的onKeyDown方法只有在界面显示时才能捕获音量变化, 要在锁屏状态或后台获得音量按键事件,可以通过判断音量值的改变来判断是否按下了音量 ...

  3. [Android] Android 锁屏实现与总结 (一)

    实现锁屏的方式有多种(锁屏应用.悬浮窗.普通Activity伪造锁屏等等).但国内比较主流并且被广泛应用的Activity伪造锁屏方式. 实例演示图片如下: 系列文章链接如下: [Android] A ...

  4. Android 锁屏键和home键分开处理

    在做视频直播的时候遇到一个问题,就是Android锁屏状态下与home键状态下SurfaceView的生命周期发生的改变是不相同的. 因为home键与锁屏的时候activity都会走onPause() ...

  5. android锁屏应用系统排行榜,重塑安卓手机的20大锁屏应用程序

    1. AcDisplay 它是一个简单的设计android锁屏应用程序,以简约的方式处理通知.您可以直接从锁定屏幕访问应用程序.它具有使用传感器唤醒设备的活动模式. 兼容性 - Android 4.1 ...

  6. jQuery仿Android锁屏图案应用

    jQuery仿Android锁屏图案应用 在线演示 本地下载 posted @ 2018-12-03 14:08 栖息地 阅读(...) 评论(...) 编辑 收藏

  7. jQuery仿Android锁屏图案应用插件

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  8. Android锁屏实现与总结

    Android锁屏实现与总结 Android锁屏实现与总结(网易云阅读) 一.自定义锁屏基本原理 二.重要步骤 1.广播注册 2.Activity设置 3.按键的屏蔽 4.滑屏解锁 5.Event b ...

  9. android 锁屏通知

    最近有个需求,说要弄个锁屏通知,通知倒是做过很多了,锁屏通知还真没弄过,经过一番研究,这里做个记录,方便搬砖. 话不多少,直接上效果图: 直接上代码: 安卓系统7以及以下: Notification. ...

最新文章

  1. 利用XSL对XML数据进行加密和大小写转换
  2. JavaScript公共运行库
  3. .net随笔-vb.net打开外部程序发送键盘信号(1)
  4. boost::geometry::default_distance_result用法的测试程序
  5. 如何处理JCO版本太旧引起的问题
  6. qq群发信息显示服务器检测到,关于如何突破QQ群发消息屏蔽或限制经验总结
  7. pytorch线性回归代码_[PyTorch 学习笔记] 1.3 张量操作与线性回归
  8. 删库不必跑路,谈数据库删除设计
  9. OpenShift Security (8) - 安装并运行 DevSecOps 应用
  10. 使用 pycharm安装各个模块
  11. ContentPresenter
  12. 吴恩达机器学习与深度学习作业目录 [图片已修复]
  13. Apache Nutch 1.3 学习笔记十一(页面评分机制 LinkRank 介绍)
  14. 报头中的偏移量作用_网络中BN层的作用
  15. DirectX8编程指南-1 (转)
  16. 修改elementUI 表格透明度,字体颜色
  17. 数据分析 第二章 1.数据清洗及特征处理
  18. 短语、直接短语、句柄、素短语
  19. 夏斌:半年宏观调控思路的建议
  20. Java波斯王子时之沙攻略_《波斯王子:时之砂》剧情攻略

热门文章

  1. qq部落android,部落守卫战手机版
  2. 物联网数据采集如何实现?
  3. 一文通透讲解Redis高级特性,多线程/持久化/淘汰机制等统统搞定
  4. 甲骨文漏洞曝光 揭秘Java安全的真相——赶快禁用java吧
  5. 软件推荐之Clover
  6. 2021 前端面试(杭州)
  7. matlab柯西主值积分,希尔伯特-黄变换基本概念
  8. 用php+mysql+ajax实现淘宝客服或阿里旺旺聊天功能 之 后台页面
  9. 第4章-变换-4.2-特殊矩阵变换和运算
  10. ICEC-电子爱好者协会-基本学习大纲(必须实行)