视频编码流程详解


1、视频编码整体流程

在这里插入图片描述


2、FFmpeg视频编码详细流程

从本地读取YUV数据编码为H264格式的数据,然后再存入到本地,编码后的数据有带startcode。
与FFmpeg示例音频编码的流程基本一致。

视频编码流程详解_第1张图片

3、关键函数说明

(1)avcodec_find_encoder_by_name:根据指定的编码器名称查找注册的编码器。

(2)avcodec_alloc_context3:为AVCodecContext分配内存。

(3)avcodec_open2:打开编码器。

(4)avcodec_send_frame:将AVFrame非压缩数据给编码器。

(5)avcodec_receive_packet:获取到编码后的AVPacket数据,收到的packet需要自己释放内存。

(6)av_frame_get_buffer:为音频或视频帧分配新的buffer。在调用这个函数之前,必须在AVFame上设置好以下属性:format(视频为像素格式,音频为样本格式)、nb_samples(样本个数,针对音频)、channel_layout(通道类型,针对音频)、width/height(宽高,针对视频)。

(7)av_frame_make_writable:确保AVFrame是可写的,使用av_frame_make_writable()的问题是,在最坏的情况下,它会在您使用encode再次更改整个输入frame之前复制它. 如果frame不可写,av_frame_make_writable()将分配新的缓冲区,并复制这个输入input frame数据,避免和编码器需要缓存该帧时造成冲突。

(8)av_image_fill_arrays:存储一帧像素数据存储到AVFrame对应的data buffer。

(9)int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align);

作用:通过指定像素格式、图像宽、图像用来计算所需的内存大小。

参数align:此参数是设定内存对齐的对齐数,也就是按多大的字节进行内存对齐:

  • 比如设置为1,表示按1字对齐,那么得到的结果就是与实际的内存大小一样。3
  • 再比如设置为4,表示按4字节对齐。也就是内存的起始地址必须是4的整倍数。

(10)int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt, int align);

  • pointers[4]:保存图像通道的地址。如果是RGB,则前三个指针分别指向R,G,B的内存地址。第四个指针保留不用 linesizes[4]:保存图像每个通道的内存对齐的步长,即一行的对齐内存的宽度,此值大小等于图像宽度。
  • w:要申请内存的图像宽度。
  • h:要申请内存的图像高度。
  • pix_fmt:要申请内存的图像高度。
  • align:用于内存对齐的值。
  • 返回值:所申请的内存空间的总大小。如果是负值,表示申请失败。

(11)int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], const uint8_t *src, enum AVPixelFormat pix_fmt, int width, int height, int align);
av_image_fill_arrays()函数本身不具备内存申请的功能,此函数类似于格式化已经申请的内存,即通av_malloc()函数申请的内存空间,或者av_frame_get_buffer()函数申请的内存空间。

  • dst_data[4]: [out]对申请的内存格式化为三个通道后,分别保存其地址;
  • dst_linesize[4]: [out]格式化的内存的步长(即内存对齐后的宽度);
  • *src: [in]av_alloc()函数申请的内存地址;
  • pix_fmt: [in] 申请 src内存时的像素格式;
  • width: [in]申请src内存时指定的宽度;
  • height: [in]申请scr内存时指定的高度;
  • align: [in]申请src内存时指定的对齐字节数。

编码出来的h264数据可以直接使用ffplay播放,也可以使用VLC播放。


4、H264的码率设置

(1)什么是视频码率?
视频码率是视频数据(包含视频色彩量、亮度量、像素量)每秒输出的位数。一般用的单位是kbps。


(2)设置码率的必要性
在网络视频应⽤中,视频质量和网络带宽占用是相矛盾的。通常情况下,视频流占用的带宽越高则视频质量也越高,需要的网络带宽也越大,解决这一矛盾的钥匙当然是视频编解码技术。评判一种视频编解码技术的优劣,是比较在相同的带宽条件下,哪个视频质量更好;在相同的视频质量条件下,哪个占用的网络带宽更少(文件体积小)。

是不是视频码率越高,质量越好呢?理论上是这样的。然而在肉眼分辨的范围内,当码率高到一定程度时,就没有什么差别了。所以码率设置有它的最优值,H.264(也叫AVC或x264)的文件中,视频的建议码率如下:
视频编码流程详解_第2张图片

(2)手机设置码率建议
视频编码流程详解_第3张图片

5、FFmpeg与H264编码指南

鉴于x264的参数众多,各种参数的配合复杂,为了使用者方便,x264建议如无特别需要可使用preset和tune设置。
这套开发者推荐的参数较为合理,可在此基础上在调整一些具体参数以符合实际需要,手动设定的参数会覆盖preset和tune的参数。

使用ffmpeg -h encoder=libx264 查询相关支持的参数。


(1)preset
预设是一系列参数的集合,这个集合能够在编码速度和压缩率之间做出权衡。
一个编码速度稍慢的预设会提供更高的压缩效率(压缩效率是以文件大小来衡量的)。这就是说,假如你想得到一个指定大小的文件或者采用恒定比特率编码模式,你可以采用一个较慢的预设来获得更好的质量。同样的,对于恒定质量编码模式,你可以通过选择一个较慢的预设轻松地节省比特率。如果你很有耐心,通常的建议是使用最慢的预设。目前所有的预设按照编码速度降序排列为:
ultrafast > superfast > veryfast > faster > fast > medium – default preset > slow > slower > veryslow > placebo - ignore this as it is not useful (see FAQ)

默认为medium级别。


(2)tune
une是x264中重要性仅次于preset的选项,它是视觉优化的参数,tune可以理解为视频偏好(或者视频类型),tune不是一个单一的参数,而是由一组参数构成-tune来改变参数设置。

当前的 tune包括:

  • film:电影类型,对视频的质量非常严格时使用该选项;
  • animation:动画片,压缩的视频是动画片时使用该选项;
  • grain:颗粒物很重,该选项适用于颗粒感很重的视频;
  • stillimage:静态图像,该选项主要用于静止画面比较多的视频;
  • psnr:提高psnr,该选项编码出来的视频psnr比较高;
  • ssim:提高ssim,该选项编码出来的视频ssim比较高;
  • fastdecode:快速解码,该选项有利于快速解码;
  • zerolatency:零延迟,该选项主要用于视频直播。

如果你不确定使用哪个选项或者说你的输入与所有的tune皆不匹配,你可以忽略–tune 选项。


(3)profile
另外一个可选的参数是**-profile:v**,它可以将你的输出限制到一个特定的 H.264 profile。一些非常老的或者要被淘汰的设备仅支持有限的选项,比如只支持baseline或者main。

所有的profile 包括:
1)baseline profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;

2)extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;

3)main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced),也支持CAVLC 和CABAC 的支持;

4)high profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式;

在相同配置情况下,High profile(HP)可以比Main profile(MP)节省10%的码流量,比MPEG-2MP节省60%的码流量,具有更好的编码性能。根据应用领域的不同:
1)baseline profile多应用于实时通信领域;
2)main profile多应用于流媒体领域;
3)high profile则多应用于广电和存储领域。

你可能感兴趣的:(音视频,音视频,编码)