ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AVS3参考软件HPM-4.1编译运行指南:从源码到码流验证

AVS3参考软件HPM-4.1编译运行指南:从源码到码流验证 你手头拿到HPM-4.1的源码包却不知道怎么把它跑起来很正常。我当年从下载源码到看到第一帧编码日志整整花了一个周末。大部分时间不是卡在编码器本身而是被Linux环境、编译器版本、配置文件路径这些外围问题绊住了。这篇东西把从HPM-4.1下载、编译、运行到验证码流的完整过程整理出来给打算研究AVS3视频编码的朋友做个参考。AVS3是国内自主制定的新一代视频编码标准在同等主观质量下码率大约比HEVC再省20%到30%。标准定了总得有个能动手跑的参考实现HPM就是AVS3参考软件里的一个重要模型。很多人第一次接触视频编码直接被各种算法术语劝退但我始终觉得先让编码器跑起来、亲手看几帧编码日志比闷头读十篇综述都管用。这篇文章适合完全没跑过AVS3参考软件、对Linux基本操作有了解的同学也适合已经在跑HM或VTM、想快速切到AVS3的人。1. 为什么研究AVS3的人绕不开这套HPM代码1.1 HPM系列在AVS3生态里的定位AVS3标准从2019年前后进入应用阶段面向8K超高清视频、广播、监控这些对压缩率要求极高的场景。标准本身是一份文本写满了编码工具的定义和语法规则但文本不能直接跑于是有了参考软件。HPMHigh Performance Model就是其中之一全称具体叫什么其实没那么重要你知道它是AVS3官方链路里的一个高性能参考实现就够了。与此相对的还有另一套偏重极致率失真性能的模型。两套模型的分工大致是一套服务于标准制定过程中的算法验证追求压缩率上限跑得慢没关系另一套偏向工程可实现性代码结构更规整、运行速度更快适合做研究开发和算法验证。HPM整体给我的感觉是它比HM和VTM更“轻”代码量没那么恐怖但对新手来说依然有门槛门槛主要不是在算法理解而是编译环境和配置链路。你如果去翻AVS3的论文会看到大量实验数据以HPM某版本作为软件锚点。换句话说别人的对比数据是在HPM上测出来的你想复现或者对比实验就要在同样的软件版本上跑。这也是我坚持用HPM-4.1的原因版本不同编码工具集和默认参数有差异结果就不具备可比性。1.2 搞懂版本号再决定用哪个模型HPM-4.1这个版本号看起来简单但背后有讲究。参考软件的版本号和标准文本的版本号不是严格同步的HPM内部维护着多个分支4.x对应的是AVS3第一阶段的工具集后续的5.x、6.x逐步加入第二阶段的工具。代码量越来越大编码性能在提升但阅读门槛也在提高。我把话说明白一点如果你是做深度学习视频编码、点云压缩、图像增强这些方向的拿HPM-4.1或者4.0做基础就够了没必要一上来就追最新版。最新版代码经过大量工具增删很多函数几百行起跳新手很容易看晕。反过来如果你就是冲AVS3第二阶段的新工具去的那必须用对应的新版模型老版本根本不支持那些工具。版本号命名本身就是个参考维度主版本代表重大架构或工具集变化次版本一般是问题修复、性能调优和工具微调。HPM-4.1相比4.0大概率就是修复了一些bug、更新了部分默认参数你在学习阶段不用纠结两个版本的具体差异挑一个顺手的版本跑通整个流程后面换版本就是重新编译的事。2. HPM-4.1环境准备依赖版本和源码目录的坑2.1 依赖清单与版本建议先说结论HPM-4.1生产于Linux环境想少踩坑就老老实实用Linux我用的是Ubuntu。在Windows上虽然也能折腾但会遇到更多路径、命令行参数解析的问题不推荐新手在Windows上起步。软件版本建议说明操作系统Ubuntu 16.04 / 18.04 / 20.04越老的代码越要靠近老环境g / gcc5.4 到 9.x太新的编译器有可能报兼容错误cmake3.5 以上不需要最新版make3.8 以上系统自带的就够ffmpeg非必需但有帮助用于生成YUV测试序列、看码流信息这里我多说一句编译器版本的问题。HPM-4.1算是2020年前后的代码那个年代的代码普遍是按C11标准写的。你现在拿Ubuntu 22.04自带的GCC 11/12去编非常容易出现一些严格检查导致的报错。所以我建议安装老一点的编译器或者用update-alternatives在多个GCC版本之间切换这个动作本身也是Linux开发的基本功。如果你不想折腾老编译器也可以尝试在编译时加一些兼容参数但效果不一定好。我见过有朋友用新版GCC强行编过补丁打了一堆最后能跑但总觉得不踏实。做研究讲究可控性环境越稳定越好。2.2 源码目录结构怎么读拿到源码包解压之后先别急着编花五分钟看一下目录结构。HPM-4.1的源码组织方式和HM、VTM这些参考软件一脉相承基本是同一个祖师爷传下来的架构。HPM-4.1/ ├── source/ │ ├── App/ # 应用入口编码器、解码器的main函数 │ │ ├── EncoderApp/ │ │ └── DecoderApp/ │ ├── Lib/ # 算法核心库 │ │ ├── Common/ # 编码器和解码器共用的数据结构 │ │ ├── Encoder/ # 编码器实现 │ │ └── Decoder/ # 解码器实现 │ └── CMakeLists.txt # 顶层CMake配置 ├── build/ │ ├── linux/ # Linux构建脚本所在目录 │ └── ... ├── bin/ # 编译产物默认输出目录 ├── cfg/ # 配置文件目录 └── READMEsource/Lib是核心里面按模块划分了文件编码器里的预测、变换、量化、熵编码、环路滤波都在Encoder目录下。source/App是入口调试的时候从main函数开始单步跟进就行。cfg目录存放编码器和解码器的配置文件大部分运行参数都在这里控制。很多人在这一步犯的错误是直接进到source/目录下执行cmake结果把一大堆临时文件散落到源码目录里最后想清理都困难。后面我会说尽量在build/目录里构建把源码目录和构建产物分开。3. cmake编译HPM-4.1的完整过程3.1 编译命令与参数说明HPM-4.1的编译流程其实很标准如果你编过VTM这套流程闭着眼都能走。先把构建目录切进去然后执行cmake指定源码路径再make即可。cd HPM-4.1/build/linux cmake ../../source -DCMAKE_BUILD_TYPERelease make -j4解释几个参数的含义-DCMAKE_BUILD_TYPERelease告诉编译器开启优化编码器的运行速度能快不少。Debug模式适合调试但编码速度会慢很多甚至慢到让人怀疑代码有问题。正常做实验一定要用Release。make -j44表示同时用4个线程编译如果你的机器核心多可以改成-j8或者-j16。但这里有个限制每个编译线程会吃几百MB内存4G内存的老机器用-j4就行别贪心。编译完成后去bin/目录看一眼正常情况下你会看到编码器和解码器的可执行文件。部分版本命名规则不完全一样可能出现HPMEncoder、HPMDecoder这种大小写混合的名字也可能叫hpm_encoder、hpm_decoder以你实际编译出来的为准。我看到有的教程会让你修改build脚本里的路径其实没必要。HPM的CMake配置一般会把可执行文件输出到bin/目录除非你手动改了CMAKE_RUNTIME_OUTPUT_DIRECTORY否则不用管。3.2 编译前你需要关注的几个报错点编译报错是新手最头疼的环节。我把自己遇到的和身边人遇到的整理一下。报错一编译器版本检查失败症状是cmake完成后make刚开始就刷出一堆带fpermissive的警告严重时直接中断。这时候先确认你的g版本g --version如果版本在11以上优先考虑换旧版本。在Ubuntu上装旧GCC并不复杂比如安装GCC-7后再切换到系统默认sudo apt-get install g-7 sudo update-alternatives --install /usr/bin/g g /usr/bin/g-7 70切换完成后再执行一次cmake最好把之前的构建缓存清掉再重新执行避免cmake缓存了旧的编译器设置。报错二找不到某个头文件或链接失败这类问题一般是系统缺少依赖库比如libtool、autoconf这类的构建辅助工具缺失。在Ubuntu上可以直接sudo apt-get install build-essential cmakebuild-essential会一次性补齐gcc、g、make等基础工具。如果还缺具体的库根据报错提示补装就行HPM的依赖不算多基本就这一轮的事情。报错三内存不足导致编译中断这种一般是并行编译线程开太多进程被系统杀掉make报一个莫名其妙的错误。遇到这种情况关掉其他大内存应用把-j后面的数字调小再试基本能解决。4. 跑通第一次编码配置文件和命令行逐项解析4.1 准备一段YUV测试序列编码器输入的原始视频一般是YUV格式HPM支持YUV420P这种最常用的格式。第一次跑实验不要直接上1080p甚至4K序列用一段小分辨率序列先验证整个链路是通的然后再考虑大序列。我在第一次跑HPM时用的是BasketballPass这个序列分辨率416x240帧率50fps只有几十帧编码时间很短跑完立刻能看到反馈。你想做实验的话用Class A到Class E的标准测试序列都行或者自己用ffmpeg从任何视频生成一段YUVffmpeg -i input.mp4 -f rawvideo -pix_fmt yuv420p -s 416x240 -r 30 -frames 30 input.yuv这段命令把任意视频转成416x240、YUV420P、30帧BRawVideo格式的YUV文件。注意-frames 30只取前30帧测试够用。YUV文件的大小可以用公式算出来宽×高×1.5就是一帧的字节数因为YUV420P每个像素对应一个亮度样本和半个色度样本。比如416x240一帧的大小是416×240×1.5 149760字节如果你看到文件的大小和帧数对不上说明序列格式和配置参数不匹配后面会详细说。4.2 配置文件关键字段说明HPM的编码器通过-c参数指定配置文件配置文件的格式跟HM、VTM的cfg文件很像每一行是“字段值”的结构。我在源码包的cfg/目录里找到参考配置文件复制了一份改成自己的参数。下面这些字段是跑第一次编码时最常遇到的InputFile ./BasketballPass_416x240_50.yuv InputBitDepth 8 SourceWidth 416 SourceHeight 240 FrameRate 50 FramesToBeEncoded 30 QP 32 StreamFile ./output.avs ReconstructionFile ./rec.yuv配置项含义注意点InputFile输入YUV文件路径必须写成实际路径相对路径以运行命令的目录为基准InputBitDepth输入像素位深常见是810bit序列要改成10SourceWidth / SourceHeight分辨率必须和YUV实际分辨率一致FrameRate帧率不影响码流语法但会影响码率计算FramesToBeEncoded要编码的帧数别大于YUV文件的总帧数QP量化参数大了画质差、码率低小了画质好、码率高新手先别改StreamFile输出码流文件编码产物可改后缀ReconstructionFile重建YUV文件编码器在编码时重建的图像用来算PSNR配置文件里字段间的空格和制表符一般都能解析但不同小版本可能有差异。最稳妥的办法是在源码包的cfg目录里找一份现成的配置文件用文本编辑器打开复制一份再改动里面的InputFile、分辨率、帧数这几个值别的先不要动。4.3 编码命令与日志阅读配置文件准备好之后开始在bin/目录下执行编码命令。注意运行目录的选择我建议在bin/目录里运行这样配置文件里的相对路径比较好写。cd HPM-4.1/bin ./HPMEncoder -c ../cfg/my_encoder.cfg如果你的可执行文件名字是hpm_encoder就把命令里的名字替换掉。命令行参数很少常见的就是-c指定配置文件有的版本还支持直接在命令行覆盖配置项比如加一个QP27但第一次跑不用关心这些。编码开始后终端会持续输出每一帧的编码信息包括帧类型、所用比特数、编码耗时、PSNR等。我第一次看到满屏刷日志的时候非常兴奋因为这意味着编码器真正跑起来了。日志里有几个信息值得重点关注帧类型I帧、P帧、B帧的分布是否符合预期。AVS3编码里GOP结构通常比较固定如果你看到疯狂刷P帧没有I帧可能配置文件中GOP设置有问题。比特数每帧消耗的比特数可以用来看不同QP下的码率变化。PSNR编码器日志自带的PSNR是你判断编码质量的直接依据后面验证的时候也可以拿这个值和外部计算的结果对比。编码结束之后检查几件事output.avs文件是否生成且大小合理rec.yuv是否存在。如果这两个文件都在说明整个编码链路已经通了。码流文件大小取决于内容和QP30帧416x240的序列QP32时通常几十KB到一百多KB如果文件是0字节或者只有几个字节肯定有问题。5. 验证码流和重建质量确认你的跑法没有错5.1 用自带解码器重建编码器给出码流还不够你要确认码流是合法可解码的否则前面全白做。HPM源码包里自带解码器在bin/目录里和编码器放在一起。解码器的用法也很简单一般是通过-b指定输入码流-o指定输出重建视频./HPMDecoder -b ../bin/output.avs -o dec.yuv参数名不同版本可能有差异我先说思路解码器的本质是读取AVS3码流按照语法规则重建出一帧一帧的图像输出YUV文件。如果解码器能成功跑完说明你编码出的码流在语法层面没有致命问题。解码完成后拿解码输出的dec.yuv和编码器输出的rec.yuv对比一下。理论上在没有错误的情况下这两个文件应该完全一致因为编码器内部也做解码重建。如果文件大小不一样或者内容对不上说明编码环节有潜在问题多半是配置文件的某个参数不对。5.2 算PSNR的两种方式PSNR是最基础的客观质量指标能直接反映编码损失的大小。算PSNR有两个路子第一个是直接用编码器日志里输出的值简单省事第二个是用ffmpeg独立计算适合你自己处理外部YUV数据时使用。用ffmpeg给两个YUV文件算PSNR的命令如下ffmpeg -f rawvideo -pix_fmt yuv420p -s 416x240 -r 50 -i rec.yuv \ -f rawvideo -pix_fmt yuv420p -s 416x240 -r 50 -i original.yuv \ -lavfi psnr -f null -解释一下这条命令-f rawvideo告诉ffmpeg输入是原始YUV文件-pix_fmt yuv420p指定像素格式-s指定分辨率-i指定输入文件。两个-i分别对应重建YUV和原始YUV顺序不能颠倒。最后的-lavfi psnr是让ffmpeg计算两路输入之间的PSNR。跑完之后终端会输出类似PSNR y:35.12 u:42.33 v:43.20 average:36.50的结果。这个值就是当前QP下的YUV分量PSNR和平均PSNR。把不同QP下的PSNR和码率记录下来就能画出一条率失真曲线这是视频编码论文里最基础的实验图。我对刚接触参考软件的人有个建议第一次跑通之后立刻用2到3个QP值各跑一遍把PSNR和码率记在表格里。一方面能验证编码器在不同参数下的稳定性另一方面你会对AVS3的RD性能有一个直观认识这比单纯看论文里的图管用得多。6. 实测中容易卡住的几个细节与排查思路6.1 YUV格式不匹配的症状跑参考软件翻车率最高的坑我认为是YUV输入格式不匹配。HPM默认读YUV420P也就是每4个亮度像素共享一对色度采样。但有些网上下载的测试序列是YUV444或者YUV422甚至YUV400只有亮度你用默认配置去读分辨率参数不对编码器读到中间就会崩溃或者输出的内容明显扭曲。判断方法很简单拿文件大小除以分辨率再乘以1.5看是不是整数帧。比如416x240的YUV420P每帧149760字节如果文件总字节数除下来不是整数帧你就要怀疑格式是不是有问题。用ffmpeg转成标准格式是最稳的ffmpeg -i any_input.mp4 -pix_fmt yuv420p -s 416x240 -r 50 test.yuv生成的test.yuv就是标准的YUV420P序列喂给HPM不会出问题。6.2 编码器只输出几帧就退出的排查这个现象我也遇到过编码器启动后刷了几帧日志然后突然报错退出。先别慌按顺序排查检查YUV文件帧数。配置文件里的FramesToBeEncoded大于实际帧数时编码器读取文件读到文件末尾行为取决于代码实现有的直接退出。检查分辨率字段。宽度和高度填错编码器把一帧数据读成错的行大小很快会在数学运算里崩掉。检查磁盘空间。输出码流文件写在磁盘上空间满了编码器会崩溃这个崩溃信息往往不那么直观。检查内存。8K分辨率、GOP较大的情况下编码内存峰值可以到好几个GB内存不足的表现也是运行中断开。排查这些有一个利器先用GDB或者直接在日志里加打印看它崩在哪个函数。但新手朋友如果只是跑通验证建议先从小分辨率、少帧数开始把变量控制住再逐步放大。6.3 编码并行配置对结果的影响HPM的编码器支持多线程并行但并行配置不是越大越好。访问参考软件的过程中我看过不少同学把线程数往上调之后编码结果出现微妙变化甚至不同线程数下PSNR对不上。这个问题根源在于编码过程中某些决策依赖全局状态强行并行会引入不确定性。我做实验的习惯是正式跑数据之前先把编码器里的并行选项关掉或者设成单线程先把一套干净的结果跑出来再开并行提速。不同版本的HPM对并行的参数名不一样有的在配置文件里就能设有的是编译期宏需要你阅读源码确认。从研究角度讲参考软件最核心的价值是确定性和可复现性。你在论文里写了用什么版本、什么配置别人照着跑能得到接近的结果这才是有效的实验。所以不到万不得已不要开那些你不知道从何而来的“优化”选项。6.4 从编译产物到调试工具的进阶参考等你把上面的流程都跑通了下一步一定会进入代码阅读和调试阶段。这时候有几个工具链能帮你大大提速VS Code Remote-SSH在服务器上开发VS Code远程连上去看代码、打断点体验比纯命令行vim好很多尤其适合一边看编码器源码一边跟踪变量。GDB编码器崩溃时用gdb ./HPMEncoder跑一遍崩在哪一目了然。不会用GDB的人建议花半天熟悉一下run、bt、next、print这几个命令调试参考软件全靠它们。ffprobe你自己生成的码流可以用ffprobe看一下基本信息虽然ffprobe对AVS3的支持程度取决于编译时是否开启了对应解码器但至少能辅助排查一部分问题。我第一次在这套环境上完整调试一段AVS3编码器代码就是在VS Code里远程连到服务器边看source/Lib/Encoder下的代码边用GDB打断点最后定位到一个环路滤波参数异常的问题。那种从“能跑”到“能改”的跨越才是你真正开始吃透AVS3的信号。说到底编译和跑通HPM-4.1只是最前面一步但它拦住了太多人。把这篇的步骤走完你至少拥有了一个可以反复做实验的AVS3平台。后续再去读编码器的帧内预测、变换量化、熵编码这些模块你会发现自己看代码的时候脑子里终于有实际编码结果可以对应了。这就是参考软件存在的意义也是视频编码学习绕不开它的原因。
返回列表