音视频知识记录

一.图像、音频、视频的基础知识

参考:
https://blog.csdn.net/qq_29350001/article/details/78226286
https://blog.csdn.net/qq_19923217/article/details/83348095
https://blog.csdn.net/d_l_u_f/article/details/7260772

1.1.采集

采集解决的是数据从哪里来的问题;图像、视频最初都是来自摄像头,而音频最初都是来自麦克风,因此,做音视频采集,就要掌握如下的技术知识

  • 系统的摄像头采集接口
    Windows:DirectShow
    Linux:V4L2
    Android:Camera
    iOS:AVCaptureSession
  • 系统的摄像头采集的参数配置
    分辨率、帧率、预览方向、对焦、闪光灯等
  • 系统的摄像头输出的图像/视频数据格式
    图片:JPEG;
    视频数据:NV21,NV12,I420等
  • 系统的麦克风采集接口
    Windows:DirectShow
    Linux:ALSA & OSS
    Android:AudioRecord
    iOS:Audio Unit
  • 系统的麦克风采集参数配置
    采样率、通道号、位宽等
  • 系统的麦克风输出的音频数据格式
    PCM

1.2.渲染

渲染解决的是数据怎么展现的问题;图像、视频最终都是要绘制到视图上面,而音频最终都是要输出到扬声器,因此,做音视频渲染,就要掌握如下的技术知识:

  • 系统提供了哪些API可以绘制一张图片或者一帧YUV图像数据
    Windows:DirectDraw,Direct3D,GDI,OpenGL等
    Linux:GDI,OpenGL等
    Android:ImageView,SurfaceView,TextureView,OpenGL等
    iOS:CoreGraphics,OpenGL等
  • 系统提供了哪些API可以播放一个mp3或者pcm数据
    Windows:DirectSound等
    Linux:ALSA & OSS等
    Android:AudioTrack等
    iOS:AudioQueue等

1.3.处理

处理解决的是数据怎么加工的问题;图像和音视频的加工,除了系统的 API,大多数都会依赖一些跨平台的第三方库的,通过掌握这些第三方库的原理和使用方法,基本上就可以满足日常音视频处理工作了,这些库包括但不限于:
图像处理:OpenGL,OpenCV,libyuv,ffmpeg等
视频编解码:x264,OpenH264,ffmpeg等
音频处理:speexdsp,ffmpeg等
音频编解码:libfaac,opus,speex,ffmpeg等

1.4.传输

传输解决的是数据怎么共享的问题,而共享最重要的是协议,所以研究音视频传输其实就是研究这些协议,常见协议如下:

  • 音视频传输前打包协议:FLV,ts,MPEG4等
  • 直播推流协议:RTMP,RTSP等
  • 直播拉流协议:RTMP,HLS,HTTP-FLV,HDL,RTSP等
  • 基于UDP的协议:RTP/RTCP,QUIC等
1.4.1.基于现有库的推流拉流
1.4.1.1.srs+ZLMediaKit

test_pusher: ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit)
srs: https://github.com/xialixin/srs_code_note

1.4.1.2.ffmpeg + nginx拉流推流

nginx环境配置:https://blog.csdn.net/zhangpengzp/article/details/89703930
ffmpeg 命令:https://www.cnblogs.com/eguid/p/10195559.html
问题:Could not find a valid device解决:https://blog.csdn.net/weixin_45617478/article/details/103449522
FFmpeg: https://github.com/FFmpeg/FFmpeg.git
x264: https://code.videolan.org/videolan/x264.git
git@code.videolan.org:videolan/x264.git
nasm: http://www.linuxfromscratch.org/blfs/view/svn/general/nasm.html

安装nginx前先安装pcre: https://sourceforge.net/projects/pcre/, openssl:http://www.openssl.org/source/(github下载OpenSSL_1_1_0l) zlib:apt install zlib1g-dev(到官方网站看版本wget http://www.zlib.net/zlib-1.2.11.tar.gz)
nginx: 下载nginx-rtmp-module git clone https://github.com/arut/nginx-rtmp-module.git
./configure --add-module=/$MODULE_INSTALL_HOME/nginx-rtmp-module
nginx添加配置: rtmp{server{listen 1935;application live{live on;}}} 或者:

		events {
			use epoll;# 选择epoll模型可以达到最佳的IO性能
			worker_connections  1024;
		}
		rtmp {                #RTMP服务
			server {
			   listen 1935;  #//服务端口
			   chunk_size 4096;   #//数据传输块的大小
			   application vod {
				   play /opt/video; #//视频文件存放位置。
			   }
			   application live{ #直播
				   live on;
				   hls on; #这个参数把直播服务器改造成实时回放服务器。
				   wait_key on; #对视频切片进行保护,这样就不会产生马赛克了。
				   hls_path /opt/video/hls; #切片视频文件存放位置。
				   hls_fragment  600s;     #设置HLS片段长度。
				   hls_playlist_length 10m;  #设置HLS播放列表长度,这里设置的是10分钟。
				   hls_continuous on; #连续模式。
				   hls_cleanup on;    #对多余的切片进行删除。
				   hls_nested on;     #嵌套模式。
			   }
		   }
		}
		http中添加:
		location /stat{
			 rtmp_stat all;
			 rtmp_stat_stylesheet stat.xsl;
		}
		location /stat.xsl{
			 root /home/cys/nginx/nginx-rtmp-module;
		}
ffmpeg: ./configure --disable-shared --disable-yasm --enable-libx264 --enable-gpl --extra-ldflags=-L/home/cys/x264-master --extra-cflags=-I/home/cys/x264-master/ --extra-libs=-ldl
ffmpeg -i rtsp://admin:ys123456@192.168.10.241/h264/ch38/main/av_stream -rtsp_transport tcp -vcodec h264 -acodec aac -f flv rtmp://192.168.10.202:1935/live

ldd ffmpeg:查看缺少什么库, 缺少使用find命令查找并添加到/usr/lib, 没找到的使用apt安装

编译问题
matroskadec.c:843: undefined reference to ‘ff_log2_tab’
原因:ff_log2_tab变量定义在log2_tab.c文件中,libavformat模块有引用到,需要包含
处理:在libavformat/matroskadec.c文件开头加上 ==》 #include “libavutil/log2_tab.c”
asvdec.c:74: undefined reference to ‘ff_reverse’
原因:同上
处理:在libavcodec/asvdec.c文件开头加上 ==> #include “libavutil/reverse.c”

二.视频编解码协议

2.1.H.264

H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准。这个标准通常被称之为H.264/AVC(或者AVC/H.264或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC)而明确的说明它两方面的开发者。
H.264协议详解:https://blog.csdn.net/qq_19923217/article/details/83348095

2.1.1.H264码流结构
2.1.2.H.264原始码流

H.264原始码流是一个接一个NALU(NAL Unit)组成,它的功能分为两层,VCL(Video Coding Layer)视频编码层和NAL(Network Abstraction layer)网络提取层。

  • VCL:包括核心压缩引擎和块、宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效地编码。
  • NAL:负责将VCL产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别

NAL是H.264为适应网络传输应用而制定的一层数据打包操作。

  • 传统的视频编码算法编完的视频码流在任何应用领域下(无论用于存储、传输等)都是统一的码流模式,视频码流仅有视频编码层VCL。
  • H.264可根据不同应用增加不同的NAL片头,以适应不同的网络应用环境,减少码流的传输差错。

在VCL进行数据传输或存储之前,这些编码的VCL数据,被映射或封装进NAL单元(NALU)。
一个原始的H.264 NALU单元常由[StartCode] [NALU Header] [NALU Payload]三部分组成,其中Start Code用于标示这是一个NALU单元的开始,必须是0x00000001、0x000001。3字节的0x000001只有一种场合下使用,就是一个完整的帧被编为多个slice的时候,包含这些slice的NALU使用3字节起始码,其余场合都是4字节的。
一个NALU = 一组对应于视频编码的NALU头部信息 + 一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)。

NALU Header由三部分组成:

  • forbidden_zero_bit:1 bit,H264规定此位必须为0;
  • nal_ref_idc:2 bits,代表优先级(0-3,3最高),表示当前NALU的重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU数据;
    • nal_ref_idc不等于0时,NAL Unit的内容可能是SPS/PPS/参考帧的片;
    • nal_ref_idc等于0时,NAL Unit的内容可能是非参考图像的片;
  • 当某个图像的片的nal_ref_id等于0时,该图像的所有片均应等于0。
  • nal_unit_type:NALU单元类型
    • 0:未使用;
    • 1:未使用分区(Data Partitioning)、非IDR图像的Slice;
    • 2:使用分区,且为Slice A;
    • 3:使用分区,且为Slice B;
    • 4:使用分区,且为Slice C;
    • 5:IDR图像的Slice;
    • 6:补充增强信息单元(SEI);
    • 7:序列参数集(Sequence Parameter Set,SPS),作用于一串连续的视频图像,即视频序列两个IDR图像之间为序列参数集,;
    • 8:图像参数集(Picture Parameter Set,PPS),作用于编码视频序列中一个或多个独立的图像;
    • 9:访问单元分隔符(Access Unit Delimiter);
    • 10:序列结束(End Of Sequence);
    • 11:码流结束(End Of Stream);
    • 12:填充数据;
    • 13-23:保留,SPS扩展;
    • 24-31:未使用;

总结:
SODB + RBSP trailing bits = RBSP
NAL header(1 byte) + EBSP(RBSP + 防伪码0x03) = NALU
Start Code Prefix(3 bytes) + NALU + Start Code Prefix(3 bytes) + NALU + …+ = H.264BitsStream
注:
SODB:String Of Data Bits,数据比特串,即编码后的最原始的数据;
RBSP:Raw Byte Sequence Payload,原始字节序列载荷,即在SODB的后面添加了trailing bits,即一个bit 1和若干个bit 0,以便字节对齐;
EBSP:Encapsulation Byte Sequence Packets,扩展字节序列载荷,在RBSP的基础上增加了防止伪起始码字节(0X03);NALU的起始码为0x000001或0x00000001,同时H264规定,当检测到0x000000时,也可以表示当前NALU的结束,如果在NALU的内部出现了0x000001或0x000000时H264就提出了“防止竞争”这样一种机制,当编码器编码完一个NAL时,应该检测NALU内部,是否出现如下图左侧的四个序列。当检测到它们存在时,编码器就在最后一个字节前,插入一个新的字节:0x03。图中0x000000和0x000001前面介绍了是起始码,0x000002是作为保留使用,而0x000003,则是为了防止NALU内部,原本就有序列为0x000003这样的数据。这样一来,当我们拿到EBSP时,就需要检测EBSP内是否有序列:0x000003,如果有,则去掉其中的0x03。这样一来,我们就能得到原始字节序列载荷:RBSP。

2.1.3.片(slice)

一个片 = Slice Header + Slice Data
片是H.264提出的新概念,实际原始视频图像数据保存在VCL层级的NAL Unit中,这部分数据在码流中被称作是片(slice)。一个slice包含一帧图像的部分或全部数据,换言之,一帧视频图像可以编码为一个或若干个slice。一个slice最少包含一个宏块,最多包含整帧图像的数据。在不同的编码实现中,同一帧图像中所构成的slice数目不一定相同。
设置片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其他片中。
片共有5种类型:I片(只包含I宏块)、P片(P和I宏块)、B片(B和I宏块)、SP片(用于不同编码流之间的切换)和SI片(特殊类型的编码宏块)。
片头规定了片的类型、属于哪个图像、有关的参考图像等;片的数据包含了一系列宏块和不编码数据。

2.1.4.宏块(Macroblock)

H.264编码的基本单位,宏块是视频信息的主要承载者,一个编码图像通常划分为多个宏块组成,包含着每一个像素的亮度和色度信息,视频解码最主要的工作则是提供高效的方式从码流中获得宏块中像素阵列。
一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个8×8 Cr彩色像素块组成。
宏块分为:

  • I宏块只能利用当前片中已解码的像素作为参考进行帧内预测;
  • P宏块可以利用前面已解码的图像作为参考图像进行帧内预测;
  • B宏块则是利用前后向的参考图形进行帧内预测。
2.1.5.I帧、P帧、B帧
  • I帧:帧内编码帧,又称intra picture;I帧通常是每个GOP(MPEG所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象。I帧可以看成是一个图像经过压缩后的产物。
    自身可以通过视频解压算法解压成一张单独的完整的图片。
  • P帧
    前向预测编码帧,又称predictive-frame;通过充分将低于图像序列中前面已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧;
    需要参考其前面的一个 I frame 或者 B frame 来生成一张完整的图片;
  • B帧
    双向预测帧,又称 bi-directional interpolated prediction frame;既考虑与源图像序列前面已编码帧,也顾及源图像序列后面已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧;
    需要参考其前一个 I 或者 P帧 及其后面的一个 P 帧来生成一张完整的图片;

PTS(Presentation Time Stamp):主要用于视频的同步和输出,在显示的时候使用;
DTS(Decode Time Stamp):主要用于视频的解码,在解码阶段使用;

2.1.6.图像组(GOP)

Group of Pictures(图像组)一个或多个解码后的图像,用于可以随机存取;
GOP一般有两个数字,如M = 3,N = 12,M制定I帧与P帧之间的距离,N指定两个I帧之间的距离。那么现在的GOP结构是:I BBP BBP BBP BB I

2.1.7.立即解码刷新(IDR)

Instantaneous Decoding Refresh;
在解码和编码中为了方便,将视频序列中第一个I帧和其他I帧区分开,所以把第一个I帧称作IDR,这样就方便控制编码和解码流程。
IDR 帧的作用是立刻刷新,使错误不致传播,从IDR帧开始,将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会,IDR帧之后的帧永远不会使用IDR之前的图像的数据来解码。

三.音频编码协议

3.1.PCM

Pulse Code Modulation,即脉冲编码调制,是对连续变化的模拟信号进行抽样、量化和编码产生的数字信号。
脉冲编码调制就是把一个时间连续,取值连续的模拟信号变换成时间离散,取值离散的数字信号后在信道中传输。脉冲编码调制就是对模拟信号先抽样,再对样值幅度量化,编码的过程。

  • 抽样,就是对模拟信号进行周期性扫描,把时间上连续的信号变成时间上离散的信号。该模拟信号经过抽样后还应当包含原信号中所有信息,也就是说能无失真的恢复原模拟信号。它的抽样速率的下限是由抽样定理确定的。抽样速率采用8Kbit/s。
  • 量化,就是把经过抽样得到的瞬时值将其幅度离散,即用一组规定的电平,把瞬时抽样值用最接近的电平值来表示。
    一个模拟信号经过抽样量化后,得到已量化的脉冲幅度调制信号,它仅为有限个数值。
  • 编码,就是用一组二进制码组来表示每一个有固定电平的量化值。然而,实际上量化是在编码过程中同时完成的,故编码过程也称为模/数变换,可记作A/D。

声音之所以能够数字化,是因为人耳所能听到的声音频率不是无限宽的,主要在20kHz以下。按照抽样定理,只有抽样频率大于40kHz,才能无失真地重建原始声音。如CD采用44.1kHz的抽样频率,其他则主要采用48kHz或96kHz。
抽样定理:设时间连续信号f(t),其最高截止频率为fm,如果用时间间隔为T <= 1/2fm的开关信号对f(t)进行抽样时,则f(t)就可被样值信号唯一地表示。在一个频带限制在(0, fh)内的时间连续信号f(t),如果以小于等于1/2fh的时间间隔对它进行抽样,那么根据这些抽样值就能完全恢复原信号。或者说,如果一个连续信号f(t)的频谱中最高频率不超过fh,这种信号必定是个周期性的信号,当抽样频率fs >= 2fh时,抽样后的信号就包含原连续信号的全部信息,而不会有信息丢失,当需要时,可以根据这些抽样信号的样本来还原原来的连续信号。根据这一特性,可以完成信号的模-数转换和数-模转换过程。

3.2.LPCM

Linear pulse code modulation,即线性脉冲编码调制,是一种非压缩音频数字化技术,是一种未压缩的原音重现,在普通CD、DVD及其他各种要求最高音频质量的场合中已经得到广泛的应用。
各种应用场合中的LPCM和PCM原理是一样的,区别在于采样频率和量化精度不同

3.3.ADPCM

Adaptive differential pulse code modulation,即自适应差分脉冲编码调制。
自适应差分脉冲编码调制是预测编码的一种,在PCM基础上进行了改进,对实际信号与按其前一些信号而得的预测值间的差值信号进行编码。
话音信号样值的相关性,使差值信号的动态范围较话音样值本身的动态范围大大缩小,用较低码速也能得到足够精确的编码效果,在ADPCM中所用的量化间隔的大小还可按差值信号的统计结果自动适配,达到最佳量化,从而使因量化造成的失真亦最小,ADPCM方式已广泛应用于数字通信、卫星通信、数字话音插空设备及变速率编码器中。
它的核心想法是:
利用自适应的思想改变量化阶的大小,即使用小的量化阶(step-size)去编码小的差值,使用大的量化阶去编码大的差值
使用过去的样本值估算下一个输入样本的预测值,使实际样本值和预测值之间的差值总是最小。

3.4.G.711

G.711是一种由国际电信联盟(ITU-T)制定的音频编码方式,又称为ITU-T G.711,是国际电信联盟ITU-T定制出来的一套语音压缩标准,代表了对数PCM(logarithmic pulse-code modulation)抽样标准,主要用于电话。
G.711主要用脉冲编码调制对音频采样,采样率为8k每秒。利用一个64Kbps未压缩通道传输语音讯号。起压缩率为1:2,即把16位数据压缩成8位。G.711是主流的波形声音编解码器。
G.711标准下主要有两种压缩算法。一种是µ-law algorithm(又称often u-law, ulaw, mu-law),主要运用于北美和日本;另一种是A-law algorithm,主要运用于欧洲和世界其他地区。其中,后者是特别设计用来方便计算机处理的。

3.5.G.726

G.726是ITU-T定义的音频编码算法。1990年CCITT(ITU前身)在G.721和G.723标准的基础上提出。G.726可将64kbps的PCM信号转换为40kbps、32kbps、24kbps、16kbps的ADPCM信号。
G.726是一种基于以16-40 kbit/s比特率运行的ADPCM的ITU-T语音编解码算法。
最为常用的方式是32 kbit/s,但由于其只是G.711速率的一半,所以就将网络的可利用空间增加了一倍。G.726具体规定了一个64 kbpsA-law或μ-law PCM信号是如何被转化为40,32,24或16 kbps的ADPCM通道的。在这些通道中,24和16 kbps的通道被用于数字电路倍增设备(DCME)中的语音传输,而40 kbps通道则被用于DCME中的数据解调信号(尤其是4800 kbps或更高的调制解调器)。

3.6.MP3

Moving Picture Experts Group Audio Layer III,即动态影像专家压缩标准音频层面3,简称为MP3,被设计用来大幅度地降低音频数据量。
利用MPEG Audio Layer 3的技术,将音乐以1:10甚至1:12的压缩率,压缩成容量较小的文件,而对于大多数用户来说重放的音质与最初的不压缩音频相比没有明显的下降。
MP3利用人耳对高频声音信号不敏感的特性,将时域波形信号转换成频域信号,并划分成多个频段,对不同的频段使用不同的压缩率,对高频加大压缩比(甚至忽略信号),对低频信号使用小压缩比,保证信号不失真,即丢弃掉脉冲编码调制(PCM)音频数据中对人类听觉不重要的数据(类似于JPEG是一个有损图像压缩)。这样一来就相当于抛弃人耳基本听不到的高频声音,只保留能听到的低频部分,从而将声音用1∶10甚至1∶12的压缩率压缩。

3.7.WAV

https://www.jianshu.com/p/b7cadd3e9c4d

WAV是最常见的声音文件格式之一,是微软公司专门为Windows开发的一种标准数字音频文件,该文件能记录各种单声道或立体声的声音信息,并能保证声音不失真。但WAV文件有一个致命的缺点,就是它所占用的磁盘空间太大(每分钟的音乐大约需要12兆磁盘空间)。它符合资源互换文件格式(RIFF)规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持。Wave格式支持MSADPCM、CCITT A律、CCITT μ律和其他压缩算法,支持多种音频位数、采样频率和声道,是PC机上最为流行的声音文件格式;但其文件尺寸较大,多用于存储简短的声音片段。
编码包括了两方面内容,一是按一定格式存储数据,二是采用一定的算法压缩数据。WAV格式对音频流的编码没有硬性规定,支持非压缩的PCM(Puls Code Modulation)脉冲编码调制格式,还支持压缩型的微软自适应差分脉冲编码调制Microsoft ADPCM(Adaptive Differential Puls Code Modulation)、国际电报联盟(International Telegraph Union)制定的语音压缩标准ITU G.711a-law、ITU G.711-law、IMA ADPCM、ITU G.723ADPCM(Yamaha)、GSM 6.10、ITU G.721 ADPCM编码和其它压缩算法。MP3编码同样也可以运用在WAV中,只要安装相应的Decode,就可以播放WAV中的MP3音乐。
PCM编码是直接存储声波采样被量化后所产生的非压缩数据,故被视为单纯的无损耗编码格式,其优点是可获得高质量的音频信号。基于PCM编码的WAV格式是最基本的WAV格式,被声卡直接支持,能直接存储采样的声音数据,所存储的数据能直接通过声卡播放,还原的波形曲线与原始声音波形十分接近,播放的声音质量是一流的,在Windows平台下被支持得最好,常常被用作在其它编码的文件之间转换的中间文件。PCM的缺点是文件体积过大,不适合长时间记录。正因为如此,又出现了多种在PCM编码的基础上经改进发展起来的编码格式,如:DPCM,ADPCM编码等。

3.8.WMA

Windows Media Audio,即微软音频格式,是微软公司推出的与MP3格式齐名的一种新的音频格式。WMA在压缩比和音质方面都超过了MP3,更是远胜于RA(Real Audio),即使在较低的采样频率下也能产生较好的音质。
WMA格式是以减少数据流量但保持音质的方法来达到压缩率更高的目的,其压缩率一般可以达到1:18,生成的文件大小只有相应MP3文件的一半。
每一个WMA文件,它的头16个字节是固定的,为十六进制的“30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”,用来标识这个是否为WMA文件。接下来的8个字节为一个整数,表示整个WMA文件头部的大小,这个头部里面包含了Tag信息等所有非音频信息,头部后面的是音频信息,我们在这里就不深入了解了。那个整数接下来的6个字节还没搞清楚是什么用的,不过不影响我们对Tag信息的读写。

3.9.AAC

Advanced Audio Coding,即高级音频编码,是一种专为声音数据设计的文件压缩格式。与MP3不同,它采用了全新的算法进行编码,更加高效,具有更高的“性价比”。利用AAC格式,可使人感觉声音质量没有明显降低的前提下,更加小巧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值