Android Video 基础笔记
文章目录
视频
- 视频文件
视频文件 .mp4 .avi 就像一个容器,类似 ArrayList 存放数据,一个视频文件可以存放多个视频,音频
ffmpeg 可以在官网下载编译好的当工具用,配置一下环境就能在 cmd 中使用
在 bin 目录下, ffmpeg.exe 编解码,视频转换; ffplay 播放器,像 ijkplayer 源码里好像是基于 ffplay 二次开发的; ffprobe 多媒体分析工具,查看文件信息。
播放视频: ffplay -i 文件路径 (-i input的意思)
播放操作可以查看时长(duration),流(stream) 等信息,播放界面左上角显示播放的是哪个流
可以选择播放哪个流: ffplay -i 文件路径 -vst 0
多个流,就类似多个视频,一个视频文件可以存放多个视频
- 编码解码
编码的目的就是为了压缩大小。 有空间冗余(图像内部相邻像素存在较强相关性造成的冗余), 时间冗余(视频图像序列中不同帧之间的相关性造成的冗余), 视觉冗余(人眼感知不到或不敏感的部分), 信息熵冗余,知识冗余等。 信息熵编码也叫统计编码包括有哈夫曼编码,香农编码,行程编码等 比如 11112222 经过行程编码得到 4142
一般视频文件存的是编码后的数据(比如第二帧只存了和第一帧不同部分的数据,来达到压缩大小的目的),所以要解码后才能播放。
视频中每帧编码方式不同 I帧(ISR):帧内编码帧,关键帧,可以单独解码出一个完整的图像 P帧:前向预测编码帧,记录本帧和前一帧(关键帧或P帧)的区别,需要用之前缓存的画面叠加本帧定义的差别,才能生成最终画面 B帧:双向预测编码帧,记录本帧和前后帧的差别。(这种压缩率最高)
视频编码 avc = h264。hevc = h265 。叫法不一样 Mediacodex 安卓编解码API MediaRecoder 编码并生成视频,但是无法操作图像数据
H.264码流文件分为两层。
- VCL(Video Coding Layer,视频编码层):负责高效的视频内容表示,VCL数据即编码处理的输出,它表示被压缩编码后的视频数据序列。VCL只关心编码部分,重点在于编码算法以及在特定硬件平台的实现,VCL输出的是编码后纯视频流信息,没有任何冗余头信息。
- NAL(Network Abstraction Layer,网络提取层):负责以网络所要求的恰当的方式对数据进行打包和传送,是传输层。不管在本地播放还是网络播放,都要通过这一层来传输。NAL关心的是VCL输出纯视频流如何被表达和封包利于网络传输。
VCL就是编码后的原始数据,在VCL数据封装到NAL单元中之后,才可以用于传输或存储。类似 javabean 序列化 json 数据
一般H.264编码器的默认输出为:起始码+NALU(Nal单元),这种格式为:Annexb格式。H.264 编码中,在每个 NAL 前添加起始码 0x00000001(4bytes)或0x000001(3bytes)
一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice), 每片包含整数个宏块(至少一个宏块,最多包含整个图像宏块),而装载着这些片(slice)的载体,就是 NAL单元。H264中宏块的大小只有 16x16
Nal Header 有8位,转成2进制,可以用与运算一个11111,取低5位获取类型 比如起始码后第一个数据67,转成1100111,取00111,得到结果类型为7,序列参数集(sps) 第1位禁止位,值为1表示语法出错 第2~3位为参考级别 4~8为是nal单元类型 然后有文档看是什么类型
H.264的SPS(序列参数集)和PPS(图像参数集)串,包含了初始化H.264解码器所需要的信息参数,包括编码所用的profile,level,图像的宽和高等。H.264码流第一个 NALU是 SPS ,第二个就是PPS,解码器需要先获取SPS与PPS才能够解码图像,然后第一个是I帧。
查看 h264 工具:010 editor 或者 搜雷神h264
- 格式 安卓采集摄像头数据可以用 Camera1,Camera2,CameraX,NDKCamera
摄像头默认 NV21 格式 编码器多数是 I420
YUV , RGB ,灰度图有公式可以互转
例如 gray = R0.30 + G0.59 + B*0.11
NV21 与I420 格式都是属于 YUV420。但是 NV21 属于 YUV420SP,而 I420 属于 YUV420P
nv21 先存 y 然后 v u 交替存储,I420 先存 y 然后存 u 最后存 v
yuv大小计算 y:w * h
u: w/2 * h/2
v: w/2 * h/2
- YUV 与 RGB 对于视频帧的裸数据,其实更多的是YUV数据格式的表示,YUV主要应用于优化彩色视频信号的传输,且能兼容老式黑白电视。与RGB相比,YUV只需要占用极少的频宽(RGB需要三个独立的视频信号同时传输)。YUV中Y代表明亮度,也称灰阶值;U与V表示的则是色度(色调和饱和度)也可以记作:YCbCr。如果只有Y数据,那么表示的图像就是黑白的。 人眼对色度不敏感,对亮度敏感,可以少压缩亮度(Y),多压缩色调和饱和度(UV),所以YUV 能比 RGB 压缩更多信息。
MediaCodec 用于访问 Android 底层的多媒体编解码器。只能编码不能生成文件,要用mediamuxer(混合器)输出媒体文件
硬编码基于硬件,软编码基于代码
- 根据图像数据编码格式计算占用内存大小 8 bit = 1 byte RGB_565 代表 R 占5位, G 占6位, B 占5位,所以 wh2 ARGB_8888 wh4 比如 1280x720的RGBA_8888图像的大小,1280 * 720 * 4=3.516M
直播
RTMP 和 HTTP 都是应用层 C 语言写的 LIBRTMP 类似 OKHTTP 封装 Socket 完成 http 数据收发,封装了 Socket 实现 RTMP 的数据收发
其他 domain socket 和平常说的 socket 不一样 是用来做 ipc 进程间通信