专栏首页音视频直播技术专家视频直播技术--Android视频采集(Camera1)

视频直播技术--Android视频采集(Camera1)

camera1.jpg

前言

今天为大家介绍一下使用Camera1进行视频采集。之前我写过一篇文章介绍的是Camera2进行视频采集。那么有人会问,为什么有了Camera2还要介绍Camera1呢?这里最主要的原因是因为Android版本众多,Camera2是Google新推出的视频采集架构,但很多老的机型还不支持,所以为了兼容性的问题,我们还不能放弃使用Camera1进行视频的采集。

下面我们来详细介绍一下 Camera1 的使用步骤。

Camera1 使用步骤

camera1使用步骤.jpeg

如图所示,使用 Camera1 的步骤包括下面几大步:

  • 设置Camera权限
  • 检查Camera是否可用
  • 打开摄像头
  • 设置摄像头参数
  • 设置预览
  • 采集数据过程

详细介绍

1. 申请Camera权限

第一步,在 AndroidManifast.xml中添加下面设置权限的语句。

<uses-permission android:name="android.permission.CAMERA" />

第二步,动态申请Camera权限。

Android在Android 6.0后,对根限的管理更严格了,除了上面要静态申请权限外,还要通过调用 requestPermissions 函数动态申请Camera权限。requestPermissions函数如下:

void requestPermissions(String[] permissions, int requestCode);

2. 检查Camera是否可用

为了程序的建壮性,在使用Camera之前我们最好检测一下设备是否可用。检测代码中下:

public static void checkCameraService(Context context)
            throws CameraDisabledException, NoCameraException {
            
    //Check if device policy has disabled the camera.
    DevicePolicyManager dpm = (DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE);
    if (dpm.getCameraDisabled(null)) {
        throw new CameraDisabledException();
    }
    
    ......
}

如果Camera服务可用,则还要检查一下Camera的个数是否为 0 ? 如果为0 ,说明Camera也是不可用的。代码如下:

    ......
    
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    int numberOfCameras = Camera.getNumberOfCameras();
    
    ......

3. 打开摄像头

    private Camera mCamera;
    
    ......
    
    Camera.CameraInfo info = new Camera.CameraInfo();

    // Try to find a front-facing camera (e.g. for videoconferencing).
    int numCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numCameras; i++) {
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mCamera = Camera.open(i);
            break;
        }
    }
   
    if (mCamera == null) {
        Log.d(TAG, "No front-facing camera found; opening default");
        mCamera = Camera.open();    // opens first back-facing camera
    }
            
    if (mCamera == null) {
        throw new RuntimeException("Unable to open camera");
    }
 
    ......

我们在打开Camera判断是否打开成功,是通过Camera对象是否为null来判断的。因为通过捕获异常有时候是不准确的。

4. 设置摄像头参数

设置摄像头参数主要是设置图像的宽、高、帧率。设置的基本步骤为:1. 从摄像头取出现有参数。2. 修改参数。3. 设置参数。

    ......
    
    Camera.Parameters parms = mCamera.getParameters();
    
    CameraUtils.choosePreviewSize(parms, desiredWidth, desiredHeight);
    
    // Try to set the frame rate to a constant value.
    CameraUtils.chooseFixedPreviewFps(parms, desiredFps * 1000);
    
    // Give the camera a hint that we're recording video.  This can have a big
    // impact on frame rate.
    parms.setRecordingHint(true);
    
    mCamera.setParameters(parms);
        
    ......

5. 设置预览

开启预览的步骤如下:1. 通过 OpenGL ES生成外部纹理。 2. 通过纹理ID行成SurfaceTexture。 3. 将生成的纹理设置到Camera中。 4. 开启预览。5. 当有视频帧到达后,使用OpengGL ES绘制图片。

    ......
    
    int[] textures = new int[1];
    GLES20.glGenTextures(1, textures, 0);
    GlUtil.checkGlError("glGenTextures");

    int texId = textures[0];
    GLES20.glBindTexture(mTextureTarget, texId);
        
    ......
    
    mCameraTexture = new SurfaceTexture(textureId);
    
    ......
    
    // Ready to go, start the camera.
    Log.d(TAG, "starting camera preview");
    try {
        mCamera.setPreviewTexture(mCameraTexture);
    } catch (IOException ioe) {
        throw new RuntimeException(ioe);
    }
    
    mCamera.startPreview();
    
    ......

绘制图片

private void frameAvailable() {
    mCameraTexture.updateTexImage();
    draw();
}

通过上面的步骤,就将 OpenGL ES 、EGL、NativeWindow以及Camera之间建立起了联接。

6.采集数据过程

  1. 打开Camera后,Camera开始采集数据。
  2. Camera会将数据存放到 mCameraTexture 中,也就是SurfaceTexture中。
  3. Camera完成一帧数据的采集后,通知应用程序有一帧数据已经准备好了。
  4. 应用程序收到通知后,调用mCameraTexture.updateTexImage(); 将SurfaceTexture中的数据输出到外部纹理(也就是GLES20.glGenTextures函数产生的纹理中)。
  5. 通过 OpenGL ES 程序将外部纹理渲染到 EGL 的 EGLSurface中。
  6. 并最终调用 EGL14.eglSwapBuffers(mEGLDisplay, eglSurface); 将 EGLSurface中的内容输出到 NativeWindow,最终显示出来。
  7. 循环执行 1-6 步。

参考

  1. 视频渲染之EGL
  2. Android视频采集Camera2
  3. http://www.jianshu.com/p/39a015f2996e

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 通过WebRTC进行实时通信-从webcam获取视频流

    在你的浏览器中打开 index.html,你将看到像下面这样子(当然是你的 webcam 中样子):

    音视频_李超
  • vim窗口管理快捷键

    音视频_李超
  • 「音视频直播技术」看ijkplayer如何使用JNI

    ijklayer可以说是目前最火的一款移动端播放器了。它同时支持Android和iOS,是由著名的B站开源的播放器库,在GitHub上有15.2K的 start...

    音视频_李超
  • 教你做一个后台相机

    做过相机的同学都知道,Camera需要一个SurfaceView来承载预览的输出流,SurfaceView的特性限制了它必须要有一个可见的View才能够使用。 ...

    PhoenixZheng
  • linux系统编程之信号(四):信号的捕捉与sigaction函数

    一、内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复...

    s1mba
  • M2Det: A Single-Shot Object Detector based on Multi-Level Feature Pyramid Network(论文解读)

    为解决目标实例尺度变化带来的问题,特征金字塔广泛用在一阶段目标检测器(比如,DSSD,RetinaNet,RefineDet)和两阶段目标检测器(比如Mask ...

    于小勇
  • [译] 在 Android 应用中使用矢量资源

    在之前的文章中,我们研究了 Android 的 VectorDrawable 图像格式以及它能够实现的功能:

    Android 开发者
  • 安装python常用软件包

    可用源: 豆瓣:https://pypi.douban.com/simple/ 清华:https://pypi.tuna.tsinghua.edu.cn/s...

    foochane
  • codeblocks文件读取之后,在输出中文时会乱码

    本来没打算写这个文,但是帮助我的大佬说可以写,正好也帮助一下可能出现这个问题的小可爱们

    阿湫
  • 搜狗财报:Q1亏损扩大、AI打响突围

    财报显示,搜狗一季度的总收入为2.573亿美元,同比增长2%,净亏损3160万美元。在此之前,彭博一致市场预期显示,搜狗Q1营收预计将达到2.51亿元美元,同比...

    刘旷

扫码关注云+社区

领取腾讯云代金券