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





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



Android RTMP 直播推流技术专栏 :


0 . 资源和源码地址 :


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

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

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

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

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

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

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

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

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

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

11. 解析 AAC 音频格式 :

12 . 将麦克风采集的 PCM 音频采样编码成 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 . 设置数据预览回调接口 :


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

② 调用的 setPreviewCallbackWithBuffer 方法原型 :

public final void setPreviewCallbackWithBuffer(PreviewCallback cb)

③ 传递的接口参数 :

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

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 格式图片
    }
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值