首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【Android RTMP】Android Camera 视频数据采集预览 ( 视频采集相关概念 | 摄像头预览参数设置 | 摄像头预览数据回调接口 )

  • 25-02-16 05:01
  • 4713
  • 11452
blog.csdn.net

文章目录

  • 安卓直播推流专栏博客总结
  • 一、 Android 端数据采集涉及到的相关概念
  • 二、 Camera 预览图像尺寸设置
  • 三、 获取摄像头采集的数据格式





安卓直播推流专栏博客总结



Android RTMP 直播推流技术专栏 :


0 . 资源和源码地址 :

  • 资源下载地址 : 资源下载地址 , 服务器搭建 , x264 , faac , RTMPDump , 源码及交叉编译库 , 本专栏 Android 直播推流源码 ;
  • GitHub 源码地址 : han1202012 / RTMP_Pusher

1. 搭建 RTMP 服务器 : 下面的博客中讲解了如何在 VMWare 虚拟机中搭建 RTMP 直播推流服务器 ;

  • 【Android RTMP】RTMP 直播推流服务器搭建 ( Ubuntu 18.04.4 虚拟机 )

2. 准备视频编码的 x264 编码器开源库 , 和 RTMP 数据包封装开源库 :

  • 【Android RTMP】RTMPDumb 源码导入 Android Studio ( 交叉编译 | 配置 CMakeList.txt 构建脚本 )

  • 【Android RTMP】Android Studio 集成 x264 开源库 ( Ubuntu 交叉编译 | Android Studio 导入函数库 )

3. 讲解 RTMP 数据包封装格式 :

  • 【Android RTMP】RTMP 数据格式 ( FLV 视频格式分析 | 文件头 Header 分析 | 标签 Tag 分析 | 视频标签 Tag 数据分析 )

  • 【Android RTMP】RTMP 数据格式 ( FLV 视频格式分析 | AVC 序列头格式解析 )

4. 图像数据采集 : 从 Camera 摄像头中采集 NV21 格式的图像数据 , 并预览该数据 ;

  • 【Android RTMP】Android Camera 视频数据采集预览 ( 视频采集相关概念 | 摄像头预览参数设置 | 摄像头预览数据回调接口 )

  • 【Android RTMP】Android Camera 视频数据采集预览 ( NV21 图像格式 | I420 图像格式 | NV21 与 I420 格式对比 | NV21 转 I420 算法 )

  • 【Android RTMP】Android Camera 视频数据采集预览 ( 图像传感器方向设置 | Camera 使用流程 | 动态权限申请 )

5. NV21 格式的图像数据编码成 H.264 格式的视频数据 :

  • 【Android RTMP】x264 编码器初始化及设置 ( 获取 x264 编码参数 | 编码规格 | 码率 | 帧率 | B帧个数 | 关键帧间隔 | 关键帧解码数据 SPS PPS )

  • 【Android RTMP】x264 图像数据编码 ( Camera 图像数据采集 | NV21 图像数据传到 Native 处理 | JNI 传输字节数组 | 局部引用变量处理 | 线程互斥 )

  • 【Android RTMP】x264 图像数据编码 ( NV21 格式中的 YUV 数据排列 | Y 灰度数据拷贝 | U 色彩值数据拷贝 | V 饱和度数据拷贝 | 图像编码操作 )

6. 将 H.264 格式的视频数据封装到 RTMP 数据包中 :

  • 【Android RTMP】RTMPDump 封装 RTMPPacket 数据包 ( 封装 SPS / PPS 数据包 )

  • 【Android RTMP】RTMPDump 封装 RTMPPacket 数据包 ( 关键帧数据格式 | 非关键帧数据格式 | x264 编码后的数据处理 | 封装 H.264 视频数据帧 )

  • 【Android RTMP】RTMPDump 推流过程 ( 独立线程推流 | 创建推流器 | 初始化操作 | 设置推流地址 | 启用写出 | 连接 RTMP 服务器 | 发送 RTMP 数据包 )

7. 阶段总结 : 阿里云服务器中搭建 RTMP 服务器 , 并使用电脑软件推流和观看直播内容 ;

  • 【Android RTMP】RTMP 直播推流 ( 阿里云服务器购买 | 远程服务器控制 | 搭建 RTMP 服务器 | 服务器配置 | 推流软件配置 | 直播软件配置 | 推流直播效果展示 )

  • 【Android RTMP】RTMP 直播推流阶段总结 ( 服务器端搭建 | Android 手机端编码推流 | 电脑端观看直播 | 服务器状态查看 )

8. 处理 Camera 图像传感器导致的 NV21 格式图像旋转问题 :

  • 【Android RTMP】NV21 图像旋转处理 ( 问题描述 | 图像顺时针旋转 90 度方案 | YUV 图像旋转细节 | 手机屏幕旋转方向 )

  • 【Android RTMP】NV21 图像旋转处理 ( 图像旋转算法 | 后置摄像头顺时针旋转 90 度 | 前置摄像头顺时针旋转 90 度 )

9. 下面这篇博客比较重要 , 里面有一个快速搭建 RTMP 服务器的脚本 , 强烈建议使用 ;

  • 【Android RTMP】NV21 图像旋转处理 ( 快速搭建 RTMP 服务器 Shell 脚本 | 创建 RTMP 服务器镜像 | 浏览器观看直播 | 前置 / 后置摄像头图像旋转效果展示 )

10. 编码 AAC 音频数据的开源库 FAAC 交叉编译与 Android Studio 环境搭建 :

  • 【Android RTMP】音频数据采集编码 ( 音频数据采集编码 | AAC 高级音频编码 | FAAC 编码器 | Ubuntu 交叉编译 FAAC 编码器 )

  • 【Android RTMP】音频数据采集编码 ( FAAC 头文件与静态库拷贝到 AS | CMakeList.txt 配置 FAAC | AudioRecord 音频采样 PCM 格式 )

11. 解析 AAC 音频格式 :

  • 【Android RTMP】音频数据采集编码 ( AAC 音频格式解析 | FLV 音频数据标签解析 | AAC 音频数据标签头 | 音频解码配置信息 )

12 . 将麦克风采集的 PCM 音频采样编码成 AAC 格式音频 , 并封装到 RTMP 包中 , 推流到客户端 :

  • 【Android RTMP】音频数据采集编码 ( FAAC 音频编码参数设置 | FAAC 编码器创建 | 获取编码器参数 | 设置 AAC 编码规格 | 设置编码器输入输出参数 )

  • 【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频解码信息 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )

  • 【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频采样数据 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )






Android 直播推流流程 : 手机采集视频 / 音频数据 , 视频数据使用 H.264 编码 , 音频数据使用 AAC 编码 , 最后将音视频数据都打包到 RTMP 数据包中 , 使用 RTMP 协议上传到 RTMP 服务器中 ;


Android 端中主要完成手机端采集视频数据操作 , 并将视频数据传递给 JNI , 在 NDK 中使用 x264 将图像转为 H.264 格式的视频 , 最后将 H.264 格式的视频打包到 RTMP 数据包中 , 上传到 RTMP 服务器中 ;


本篇博客中主要讲解 Android 端数据采集 , Camera 摄像头设置 ;





一、 Android 端数据采集涉及到的相关概念



1 . 图像采集显示组件 : 布局文件中添加 SurfaceView , 用于在该 SurfaceView 组件中预览 Camera 采集的图像数据 ;



2 . Android 摄像头常量 : Android 中使用特定的常量指定使用哪个摄像头 ;


① 指定后摄像头 : 使用 Camera.CameraInfo.CAMERA_FACING_BACK 常量 , 指定后摄像头 ;

② 指定前摄像头 : 使用 Camera.CameraInfo.CAMERA_FACING_FRONT 常量 , 指定前摄像头 ;



3 . 码率 与 帧率 :


① 码率 : 单位时间内 , 传输的视频数据的位数 , 单位是 BPS ;

② 码率与视频质量 : 码率与视频编码后的数据量成正比 , 码率越高 , 允许的数据量大小越高 , 视频越清晰 , 数据量随之变大 ;

③ 码率极限值 : 码率不是越大越好 , 码率有一个极限值 , 固定的宽高的视频码率有一个最大值 , 高于该最大值 , 没有任何意义 , 不能提升视频质量 ;

④ 帧率 : FPS , 界面刷新频率 , 单位 赫兹 Hz , 每秒刷新的画面次数 ;





二、 Camera 预览图像尺寸设置



Camera 采集图像数据时 , 会通过指定的回调函数返回图像数据 , 这些图像数据称为预览数据 , 图像肯定有对应的尺寸 , 这些尺寸是 Camera 启动时设置的 , 称为预览尺寸 PreviewSize ;



1 . Camera 预览图像尺寸设置 :


① 用户设置测图像预览尺寸 : 用户设置 Camera 参数时 , 会设置一个 Camera 摄像头预览图像宽高参数 , 这个值用户可以随意设置 ;

② 系统预置的 Camera 预览尺寸 : 但是实际上 , Android 系统中的 Camera 摄像头的尺寸参数必须从几个预置的预览尺寸中选择 , 这些预览尺寸是厂家设定好的 , 用户无法设置 Camera 的语言尺寸 ;


厂家为该 Camera 预置了若干个预览尺寸 , 需要选择一个用户设置的尺寸与系统预置尺寸差距最小的那个 , 才能更好的实现用户意图 ;



2 . 预览尺寸选择方法 :


① 用户设置像素总数 : 用户设置的宽高像素值相乘, 就是用户设置像素总数 ;

② 系统支持像素总数 : 屏幕支持的 宽 高 像素值相乘, 就是系统支持的某个宽高的像素总数 ;

③ 选择尺寸 : 找出一个系统预置的预览尺寸的 系统支持像素总数 , 该数值与 用户设置像素总数 最接近即可 , 该预览尺寸就是要设置给 Camera 的预览尺寸 ;


3 . 代码示例 : 根据用户设置的尺寸 , 选择最接近的 Camera 支持的预览尺寸值 ;

    /**
     * 用户设置的高度
     */
    private int mHeight;

    /**
     * 用户设置的宽度
     */
    private int mWidth;

    /**
     * 设置 Camera 摄像头的参数
     * 宽度, 高度
     *
     * 摄像头支持的宽高值是固定的, 不能人为的随意设置
     * 手机给出一组支持的宽高值, 可以选择其中的某一个进行设置
     *
     * 用户虽然设置了一个宽高值, 这个宽高值肯定不能直接设置给 Camera 摄像头
     * 需要对比 Camera 支持的一组宽高值, 哪一个与用户设置的最接近
     * 这个最相似的宽高值就是我们要设置的值
     *
     * 对比方法 : 对比像素总数
     * 用户设置像素总数 : 用户设置的 宽 高 像素值相乘, 就是用户设置像素总数
     * 系统支持像素总数 : 屏幕支持的 宽 高 像素值相乘, 就是系统支持的某个宽高的像素总数
     *
     * 找出上述 用户设置像素总数 和 系统支持像素总数 最接近的的那个 系统支持像素总数
     *      对应的 屏幕支持的 宽 高 值
     *
     * @param parameters
     */
    private void setPreviewSize(Camera.Parameters parameters) {
        // 1. 获取摄像头参数中的预览图像大小参数
        List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();


        // 2. 下面开始遍历获取与用户设置的宽高值最接近的, Camera 支持的宽高值


        // 获取系统 Camera 摄像头支持的最低的摄像头
        //      Camera.Size 中有宽度和高度参数
        Camera.Size currentSupportSize = supportedPreviewSizes.get(0);
        // 对比第 0 个系统支持的像素总数 与 用户设置的像素总数 差值
        //      之后会逐个对比, 每个系统支持的像素总数 与 用户设置像素总数 差值
        //      选择差值最小的那个像素值
        int minDeltaOfPixels = 
        	Math.abs(currentSupportSize.height * currentSupportSize.width - mWidth * mHeight);
        // 对比完成之后, 删除像素值
        //supportedPreviewSizes.remove(0);

        // 遍历系统支持的宽高像素集合, 如果
        Iterator<Camera.Size> iterator = supportedPreviewSizes.iterator();
        while (iterator.hasNext()) {
            // 当前遍历的的系统支持的像素宽高
            Camera.Size tmpSupportSize = iterator.next();
            // 计算当前的设备支持宽高与用户设置的宽高的像素点个数差值
            int tmpDeltaOfPixels = 
            	Math.abs(tmpSupportSize.height * tmpSupportSize.width - mWidth * mHeight);

            // 如果当前的差分值 小于 当前最小像素差分值, 那么使用当前的数据替代
            if (tmpDeltaOfPixels < minDeltaOfPixels) {
                minDeltaOfPixels = tmpDeltaOfPixels;
                currentSupportSize = tmpSupportSize;
            }
        }

        // 3. 选择出了最合适的 Camera 支持的宽高值
        mWidth = currentSupportSize.width;
        mHeight = currentSupportSize.height;

        // 4. 为 Camera 设置最合适的像素值
        parameters.setPreviewSize(mWidth, mHeight);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72




三、 获取摄像头采集的数据格式



1 . 设置数据预览回调接口 :


① 设置方法 : Android 中的摄像头 Camera 通过调用 setPreviewCallbackWithBuffer 函数 , 传递一个回调接口对象 ;

② 调用的 setPreviewCallbackWithBuffer 方法原型 :

public final void setPreviewCallbackWithBuffer(PreviewCallback cb)
  • 1

③ 传递的接口参数 :

public interface PreviewCallback{
	void onPreviewFrame(byte[] data, Camera camera);
}
  • 1
  • 2
  • 3

2 . PreviewCallback 回调接口的作用 : PreviewCallback 接口中定义了 onPreviewFrame 方法 , 该方法中的 byte[] data 参数就是摄像头采集的数据 ;


3 . 采集到的图像数据 : 这是摄像头采集的图像数据 , Android 中的 Camera 摄像头采集数据成功后 , 就会回调该 PreviewCallback 接口中的 onPreviewFrame 方法 , 可以让用户获取并使用这些图像数据 ;


这是数据的格式是 NV21 格式的 ;

    // 设置 Camera 预览数据回调接口
	mCameraHelper.setPreviewCallback(this);

	// ....

    /**
     * Camera 摄像头采集数据完毕, 通过回调接口传回数据
     * 数据格式是 nv21 格式的
     * @param data
     * @param camera
     */
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        // 处理该获取的 Camera 采集的 data 数据, nv21 格式图片
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
注:本文转载自blog.csdn.net的韩曙亮的文章"https://blog.csdn.net/shulianghan/article/details/106675696"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top