流程
从本地读取YUV数据编码为h264格式数据,再存入本地,编码后的数据有带startcode
与FFmpeg音频编码流程基本一致。
函数说明
-
avcodec_find_encoder_by_name:根据指定的编码器名称查找注册的编码器。
-
avcodec_alloc_context3:为AVCodecContext分配内存。
-
avcodec_open2:打开编码器,让AVCodecContext与编码器关联。
-
avcodec_send_frame:将AVFrame非压缩数据给编码器。
-
avcodec_receive_packet:获取编码后的AVPacket数据。
-
av_frame_get_buffer:为音频或视频数据分配新的buffer
注:调用这个函数之前,必须给AVFrame设置好以下属性:
- Format(视频为像素格式,音频为样本格式)
- nb_samples(样本个数,针对音频)
- Channel_layout(通道类型,针对音频)
- width/height(宽高,针对视频)
-
av_frame_make_writable:确保AVFrame是可写的,尽可能避免数据的复制。如果AVFrame不是可写的,将分配新的buffer和复制数据。
-
av_image_fill_arrays:将一帧像素数据存储到AVFrame对应的data buffer
编码出来的h264数据可以直接使用ffplay播放。
av_image_get_buffer_size
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align);
函数的作用是通过指定像素格式、图像宽高来计算所需的内存大小。
重点说明一个参数align:此参数是设定内存对齐的对齐数,也就是一行数据按多大的字节的整数倍进行内存对齐,对不齐的要补充对应字节内存对齐:
- 比如设置为1,表示按1字节对齐不需要补齐内存,那么得到的结果就与实际内存大小一样。
- 再比如设置为4,表示按4字节对齐。也就是内存的起始地址必须是4的整数倍
av_image_alloc
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的内存地址。第四个指针保留不用。
- linesize[4]:保存图像每个通道的内存对齐的步长,即一行的对齐内存宽度,此值大小等于图像宽度。
- w:图像宽度
- h:图像高度。
- Pifx_fmt:像素格式。
- align:用于内存对齐的值。
- 返回值:所申请的内存空间总大小。如果是负值,表示申请失败。
av_image_fill_arrays
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]包含或包含实际图像数据的缓冲区,可以为 NULL。
H264码率设置
什么是视频码率
视频码率是视频数据(包括视频色彩量、亮度量、像素量)每秒输出的位数,一般用的单位是kbps。
设置视频码率的必要性
是不是码率越高,视频质量越好呢?理论上是这样的。然而在我们肉眼分辨的范围内,当码率高到一定程度时就没什么差别了。所以码率设置有它的最优值,H264(也叫AVC或X264)的文件中,视频建议码率如下:
手机设置码率建议
x264编码指南-码率控制
参考:雷神文章t.csdn.cn/Gw2Uw