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





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



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 摄像头获取 NV21 数据后 , 将 NV21 数据转为 x264 需要的 I420 数据 , 然后将 I420 数据编码成 H.264 格式的数据 ;





一、 NV21 与 I420 数据格式转换



1 . 采集数据 :


① Camera 采集的数据 : 上面讲解了 Camera 摄像头采集图像数据之后 , 会回调 PreviewCallback 接口的 onPreviewFrame 方法 , onPreviewFrame 方法的 byte[] data 参数 , 就是 Camera 采集的图像数据 ;

② 采集的数据格式 : Camera 采集的图像数据是 NV21 格式的 ;



2 . x264 接收的格式 :


① RTMP 推流过程 : 在 RTMP 推流过程中 , 手机 Camera 采集到数据后 , 需要先使用 x264 将数据编码成 H.264 格式的 , 然后将 H.264 数据打包成 RTMP 数据 ;

② x264 接收格式 : x264 开源库的输入数据类型必须是 I420 格式 , 这里就涉及到了将 Camera 采集的 NV21 格式的数据 , 转为 x264 开源库需要的 I420 格式的数据 ;



3 . YUV420 格式 :


① 两个分支格式 : NV21 图像格式I420 图像格式都属于 YUV420 图像格式的分支 ;

② YUV 说明 : YUV 各种中的 Y 表示明亮度和灰度 , UV 表示色度和饱和度 ;

③ 黑白图片 : 如果只有 Y 数据 , 那么就是灰度图片 , 这张图片是黑白的 ; UV 数据表示的是图像的色彩 ;

④ 存储原理 : 灰度数据 Y 保证全部满足 , 多个灰度数据公用 UV 色彩数据 , 这样就可以减少图像数据的大小 ;





二、 NV21 数据格式



NV21 图像格式数据排列 : 4 × 4 4 \times 4 4×4 像素的图片为例 , 其有 16 16 16 个 Y 数据 , UV 数据只有 4 4 4 组 , 共 8 8 8 个 ;


① 数据的排列格式如下矩阵 :

[ y 1 y 2 y 3 y 4 y 5 y 6 y 7 y 8 y 9 y 10 y 11 y 12 y 13 y 14 y 15 y 16 v 1 u 1 v 2 u 2 v 3 u 3 v 4 u 4 ] \begin{bmatrix} y1 & y2 & y3 & y4 \\\\ y5 & y6 & y7 & y8 \\\\ y9 & y10& y11& y12 \\\\ y13& y14& y15& y16 \\\\ v1 & u1 & v2 & u2 \\\\ v3 & u3 & v4 & u4\\ \end{bmatrix} y1y5y9y13v1v3y2y6y10y14u1u3y3y7y11y15v2v4y4y8y12y16u2u4


② 内存中的数据表示 : 这也是 NV21 数据中的数组排列方式 , 每个 YUV 数据各占 1 1 1 字节 , 如 1 1 1 个 Y 数据占 1 1 1 字节 ;

byte[] data = {
	y1 , y2 , y3 , y4 ,
	y5 , y6 , y7 , y8 ,
	y9 , y10, y11, y12,
	y13, y14, y15, y16,
	v1 , u1 , v2 , u2 , 
	v3 , u3 , v4 , u4 , 
}

③ 数据使用情况 :

  • 灰度数据 y1 , y2 , y5 , y6 使用的是 v1 , u1 色彩数据 ;
  • 灰度数据 y3 , y4 , y7 , y8 使用的是 v2 , u2 色彩数据 ;
  • 灰度数据 y9 , y10, y13, y14 使用的是 v3 , u3 色彩数据 ;
  • 灰度数据 y11, y12, y15, y16 使用的是 v4 , u5 色彩数据 ;




三、 I420 数据格式



I420 图像格式数据排列 : 4 × 4 4 \times 4 4×4 像素的图片为例 , 其有 16 16 16 个 Y 数据 , UV 数据只有 4 4 4 组 , 共 8 8 8 个 ;


① 数据的排列格式如下矩阵 :

[ y 1 y 2 y 3 y 4 y 5 y 6 y 7 y 8 y 9 y 10 y 11 y 12 y 13 y 14 y 15 y 16 u 1 u 2 u 3 u 4 v 1 v 2 v 3 v 4 ] \begin{bmatrix} y1 & y2 & y3 & y4 \\\\ y5 & y6 & y7 & y8 \\\\ y9 & y10& y11& y12 \\\\ y13& y14& y15& y16 \\\\ u1 & u2 & u3 & u4 \\\\ v1 & v2 & v3 & v4\\ \end{bmatrix} y1y5y9y13u1v1y2y6y10y14u2v2y3y7y11y15u3v3y4y8y12y16u4v4


② 内存中的数据表示 : 这也是 NV21 数据中的数组排列方式 , 每个 YUV 数据各占 1 1 1 字节 , 如 1 1 1 个 Y 数据占 1 1 1 字节 ;

byte[] data = {
	y1 , y2 , y3 , y4 ,
	y5 , y6 , y7 , y8 ,
	y9 , y10, y11, y12,
	y13, y14, y15, y16,
	u1 , u2 , u3 , u4 , 
	v1 , v2 , v3 , v4
}

③ 数据使用情况 :

  • 灰度数据 y1 , y2 , y5 , y6 使用的是 v1 , u1 色彩数据 ;
  • 灰度数据 y3 , y4 , y7 , y8 使用的是 v2 , u2 色彩数据 ;
  • 灰度数据 y9 , y10, y13, y14 使用的是 v3 , u3 色彩数据 ;
  • 灰度数据 y11, y12, y15, y16 使用的是 v4 , u5 色彩数据 ;




四、 NV21 格式与 I420 格式对比



NV21 格式与 I420 格式对比 :


① 数据量 : 相同像素点数的图像 , 其数据大小是相同的 ;

② Y 灰度值排列 : 其灰度值排列方式是相同的 , 都是在 1 ~ 16 位置依次排列 16 个像素点数 ;

③ UV 色彩值排列 : 其色彩值排列是不同的 ,

  • NV21 格式中 , UV 色彩值是交替排序的 , v1 , u1 , v2 , u2 , v3 , u3 , v4 , u4 ;

  • I420 格式中 , UV 色彩值是 4 4 4 个 u 先排列 , 然后排 4 4 4 个 v 数据 , u1 , u2 , u3 , u4 , v1 , v2 , v3 , v4 ;





五、 NV21 与 I420 图像大小



NV21 与 I420 图像大小 :


① 推导过程 :

  • 4 4 4 像素值数据 : 4 4 4 个像素值 , 有 4 4 4 个 Y 灰度数据 , 占 4 4 4 字节 ; 1 1 1 个 Y 和 1 1 1 个 U 数据 , 占 2 2 2 字节 ;

  • 4 4 4 像素值数据大小 :总共有 4 + 1 + 1 = 6 4 + 1 + 1 = 6 4+1+1=6 字节 ;

  • 4 4 4 个像素对应 6 6 6 个字节 ;

  • 归纳 : n n n 个像素对应 n × 3 2 \cfrac{n \times 3}{2} 2n×3 个字节数据 ;


② 计算公式为 : 已知图像像素的宽度和高度 ;

图 像 大 小 ( 字 节 ) = 宽 度 × 高 度 × 3 2 图像大小 ( 字节 ) = \cfrac{宽度 \times 高度 \times 3}{2} ()=2××3





六、 NV21 格式转为 I420 格式算法



NV21 格式与 I420 格式的区别只是 UV 色彩值的排列方式不一样 , NV21图像转为 I420 图像 , 只需要将 NV21 格式图像交替排列的 UV 数据 , 按照 I420 格式图像的先 U 后 V 的顺序重新进行排列即可完成图像格式转换 ;


先将 NV21 格式数据中的 Y 灰度数据拷贝出来放在一个数组中 , 再将 NV21 数据中的 V 数据 , 和 U 数据分别拷贝出来 , 这里得到三个数组 , 分别存储 Y 数据 , U 数据 , V 数据 ;


将 NV21 数据中的 V 数据 , 和 U 数据分别拷贝出来的方式时 , 读取 Y 数据完毕后 , 取下一个数据就是 V 数据 , 放入 V 数组 , 再取下一个数据就是 U 数据 , 放入 U 数组 , 之后继续获取数据 , 交替放入 V 数组 / U 数组 , 最终就得到了 3 3 3 个数组 , 即 Y 数组 , U 数组 , V 数组 ;

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值