江韬 · 12月12日 · 江苏

CIX ffmpeg transcoding pipeline优化

FFmpeg 的转码过程本质是多媒体数据在不同模块间有序流转、格式转换的过程,核心依赖解复用(Demux)、解码(Decoder)、滤镜(Filter)、编码(Encoder)、复用(Mux)五大核心模块的紧密耦合,最终形成闭环的转码 Pipeline。

Demux(解复用器):负责从输入的封装文件(如 MP4、MKV、FLV)中,分离出独立的音视频流(Audio Stream、Video Stream)和元数据(如时长、码率)。例如从 MP4 文件中,Demux 会将 H.264 编码的视频流和 AAC 编码的音频流分开,输出格式为AVPacket(封装编码后的数据,包含时间戳、流索引等关键信息)。
Decoder(解码器):接收 Demux 输出的 AVPacket,通过对应编码格式的解码算法(如 H.264 解码器、AAC 解码器),将压缩的编码数据转换为原始裸数据。其中视频流解码后输出AVFrame(包含 YUV/RGB 像素数据、宽高、像素格式等),音频流解码后输出 AVFrame(包含 PCM 采样数据、采样率、声道数等)。
Filter(滤镜器):对解码后的原始 AVFrame 进行处理,实现画质 / 音质优化、格式适配等功能。例如视频滤镜可完成图像格式转换(format)、分辨率缩放(scale)、帧率调整(fps)、水印叠加(overlay),音频滤镜可完成音量调节(volume)、采样率转换(aresample)。Filter 处理后输出的仍是 AVFrame,但数据参数已根据需求调整。
Encoder(编码器):接收 Filter 处理后的 AVFrame,通过指定编码格式的编码算法(如 H.265 编码器、MP3 编码器),将原始裸数据重新压缩为编码数据,输出格式回归为 AVPacket(包含编码后的数据、新的时间戳和码率信息)。
Mux(复用器):接收 Encoder 输出的音视频 AVPacket,按照目标封装格式(如输出为 MKV、MP4)的规范,将音视频流重新打包整合,同时写入元数据,最终生成完整的目标输出文件。一个典型的转码命令如下所示

image-2025-11-14_15-16-42.png

CIX FFmpeg将重点对pipeline中v4l2m2m的编解码器做增强与优化,以充分利用VPU硬件加速,提升转码效率,降低CPU资源使用。

v4l2m2m encoder时序优化

如图所示为FFmpeg发行版收发包时序

 title=

可见,发行版FFmpeg收一帧图像AVFrame,编一帧,输出一帧码流AVPacket。这样做有两大缺点:

  1. 底层硬件编码分为元数据和宏块数据编码两部分,在硬件单元中可对多帧输入并行执行。如果仅仅输入一帧并等待输出,则无法充分利用硬件并行运行性能。
  2. 此种时序只支持显示顺序与编码顺序一致的场景,即无法支持B帧。后果是编码压缩效率较低。

针对发行版缺点,CIX FFmpeg修改新的encoder时序为:
 title=

CIX FFmpeg会尽可能将output buffer传入driver。并采用非阻塞poll轮询结果。一方面充分利用硬件并行运行机制,另一方面因为需要支持B帧编码,一帧图像输入并非一定有输出,如果采用永久等待的阻塞poll会卡死。另外,为了防止过多的轮询,当output buffer都已经传入driver时,会采用永久等待的阻塞式poll等待输出。由于output buffer数目由vpu driver决定,能够保证,当所有output buffer queue入driver时,一定能编出一帧。

引入DMABUF

发行版FFmpeg仅支持V4L2\_MEMORY\_MMAP类型的v4l2 buffer。CIX FFmpeg新增V4L2\_MEMORY\_DMABUF,原因有如下几点:

1.MMAP最大32个buffer,在某些码流转码时,因为mux并不能及时将capture buffer归还,所以某一时刻所需buffer数目超过上限。引入DMABUF后,每一个v4l2buffer只是相当于一个槽位,可以装填不同的dmabuf,如此便可以消除上限限制。并且可以动态的根据loading申请回收dmabuf,更优的分配buffer数目。

2.decoder在drain时,需要所有capture buffer释放才能结束,但是在一些播放器应用中,后级渲染显示模块会缓存几帧frame,使得decoder drain无法完成。引入dmabuf后,可以把dmabuf送往后级,并释放capture buffer。当drain结束时,可以为v4l2 buffer分配新的dmabuf,并且老的dmabuf归还时直接释放,即可实现capture buffer和dmabuf的解耦。这样,cix FFmpeg就解决了原生版本无法解码dynamic resolution码流的问题。

2.1 实现dmabuf,可以由v4l2m2m自行决定buffer sync执行时间,同步方向。例如,如果是解码器输出dmabuf给下一级,并且是GPU渲染,可以不执行向CPU的同步操作,这样就节省一次sync操作,提高性能。
2.2 mmap可以export出dmabuf fd,但是会为每一个vb2 plane分配一个fd。例如输出格式是NV12M,即会export出2个fd。但是对于firefox这种应用,只能处理一个fd,即NV12格式。这样用mmap type的memory就无法兼容firefox。引入dmabuf后,可以实现只分配一个fd,并且针对NV12M格式,可以为各个plane计算针对一个fd的offset和length,这样就兼容了NV12和NV12M两种格式。可让firefox不做修改,即可使用v4l2m2m的codec进行硬件加速。
2.3 硬件downscale适配
以一条常规的转码命令为例:

ffmpeg -c:v h264\_v4l2m2m -vsync 0 -i ~/big\_buck\_bunny\_1080p\_h264.mov -vf “scale=1280:720” -codec:v:0 hevc\_v4l2m2m -gop\_type pyramid -b:v 3000k -bf:v 3 -g 120 bbb\_720p.mp4

此命令将原始码流big\_buck\_bunny\_1080p\_h264.mov利用h264格式的v4l2m2m codec解码,输出1080p分辨率的图像,并由swscaler缩小至720p。紧接着把处理后的图像送入hevc格式的v4l2m2m codec进行编码,码率是3M,最大3帧B帧,最后合成mp4文件保存。

若按照发行版FFmpeg,需要swscaler进行图像缩放功能,非常耗时,并且占用大量CPU资源,使得转码最大路数受限。

CIX VPU解码器包含post process处理模块,可对输出frame进行硬件加速的downscale(缩小)。CIX FFmpeg会解析filter参数,并解析swscaler参数,如果合法,可以设置decoder输出为720p,这样,swscaler无需任何处理,可直接把decoder输入送入encoder。如此,一方面充分利用硬件特性,加速转码效率,二来减少CPU资源的使用,可以承载更多路数的转码的工作。

CIX FFmpeg对downscale的操作对于用户而言是透明的,无需用户设置。另外CIX FFmpeg对于“scale”的解析也支持各种表达式,例如为实现等比例缩小并且宽为1280,缩写的表达式为:

scale=trunc(min(max(iw\,ih_a)\,1280)/64)_64:trunc(ow/a/2)*2

10bit->8bit优化

以一条10bit p010格式的码流转码成8bit 格式为例:

ffmpeg -y -c:v hevc\_v4l2m2m -i /swtest/MM/stream/mp4/'Lost Places 8K HDR-HEVC-30FPS.mp4' -filter:v format=nv12 -c:v hevc\_v4l2m2m -profile:v main -rc\_mode 0 -b:v 60000000 -g 600 -keyint\_min 600 -bf 3 -vframes 18 -c:a copy output.mp4

此命令采用-filter:v 滤波器将decoder输出的p010le格式图像,转换成nv12格式并作为输入由encoder进行编码。

CIX FFmpeg会解析filter中的format格式(例如nv12,yuv420等等),如果是VPU post process可以输出的格式,可以直接设定decoder输出为该格式。这样就省去了软件转换图像格式的过程,即提高转码性能又减少CPU资源占用。这些操作,也由CIX FFmpeg透明地执行,无需用户干预。

推荐阅读
关注数
1
内容数
1
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息