尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

视频编解码算法工程师笔试复盘:H.264/H.265核心考点与工程实践

视频编解码算法工程师笔试复盘:H.264/H.265核心考点与工程实践 2018年秋天欢聚时代校招笔试成都场视频编解码算法工程师A卷。我记得那天笔试教室里人不多不少人都是奔着音视频这条赛道来的毕竟那时候直播和短视频正在风口上。放下卷子扫了一遍第一感觉是这套题没有一道是虚的考点几乎全锁在“视频编解码”和“算法”这两个词上而且有个很鲜明的特点——每道题都在试探你是背过面试题的学生还是真正写过编码器的人。这份复盘写给三类人正在准备校招或社招的音视频岗位候选人、刚转行做编解码开发想补齐底子的同行、以及纯粹好奇一套编解码算法笔试卷子长什么样的人。原题的具体表述我记不完全了但考点的覆盖范围和出题思路后来和参加过同场次的同学对过基本就是下面这个结构而且现在回头看很多内容放到今天依然适用。1. 笔试题型全景这套卷子到底在考什么1.1 整体题型结构与时间分配整套卷子满分为100分时长我记得是90分钟题量不算小。答题顺序和时间分配很关键。从题型分布来看大致是这么个结构题型大致分值题量考察方向选择题30分15题左右H.264/H.265基础概念、颜色空间、码率控制、质量评价简答题30分4-5题帧类型与GOP、率失真优化、去块滤波、H.265改进点编程与算法题40分2-3题数据结构基础、视频处理场景算法、手写代码能力选择题基本是送分题但前提是你真的理解概念而不是死记硬背。比如“I帧一定比P帧体积大吗”“QP值调大是更清晰还是更模糊”“4:2:0采样下每像素平均多少比特”这类题只要搞懂原理就不会错。简答题考的是知识体系的完整性需要把原理和工程取舍讲清楚一两句话带过是拿不到分的。最后的编程题才是拉开差距的地方也是这套卷子真正筛选人的关键。我建议做题顺序是先快速扫一遍所有题目把有把握的选择题做完然后直接去做编程题。因为编程题一旦卡住需要的时间不可控最后如果代码没写完即便前面答得再好也很可惜。简答题放在编程和选择之间它不需要大块时间思考写到点子上就能拿分。1.2 视频编解码核心考点分布把整套卷子的考点拉出来看可以分成下面几条主线码流结构NAL单元、SPS/PPS参数集、IDR帧和普通I帧的区别。帧类型与参考关系I帧、P帧、B帧的压缩原理GOP结构显示顺序和编码顺序的关系。预测编码帧内预测的方向模式帧间预测的运动估计、运动补偿、MV预测规则。变换量化DCT整数变换量化参数QP和量化步长的换算关系。熵编码CAVLC和CABAC的基本思想为什么CABAC压缩率更高。环路滤波去块滤波原理、边界强度计算、H.265引入SAO的作用。率失真优化拉格朗日代价函数的形式λ和QP的关系。质量评价PSNR、SSIM的原理与应用场景。颜色空间YUV与RGB的转换4:2:0、4:2:2、4:4:4采样的含义。码率控制CBR、VBR、ABR、CRF这几种方式各自的适用场景。看到没这套题的覆盖面相当广。从码流格式到像素采样从宏块预测到熵编码统计基本把视频编解码链条上的每一个关键环节都问了一遍。它不是让你背某个编码标准的某个表格而是要求你在脑子里建立起一条完整的知识链路原始视频进来怎么变成YUV——怎么分块做预测——残差怎么变换量化——怎么熵编码成码流——解码端逆向走一遍。我考完最深的感受是如果只做过API调用的开发比如用FFmpeg转个封装格式、用x264压个视频不去看底层的码流结构选择题后面十几道题基本要靠蒙。但如果你自己动手跑过参考软件、分析过码流哪怕只是调过编码器参数观察质量变化这套卷子就是给你准备的。1.3 为什么这些考点在编解码笔试里反复出现很多人问笔试不是应该考工程能力吗为什么盯着这些底层原理不放答案在岗位名称上——视频编解码算法工程师。这个岗位的工作不是调用FFmpeg命令而是做三件事第一优化编码器的编码效率在同等码率下让画质更好第二适配不同的硬件平台比如ARM、DSP、GPU做算法移植和SIMD优化第三解决实际业务中的画质问题比如直播场景下带宽浮动引起的花屏、卡顿短视频场景下的编码加速。要完成这三件事底层原理就是基本功。不清楚率失真优化就不知道编码器在什么条件下会牺牲画质不清楚参考帧管理和GOP结构就不知道怎么设计一个适合网络丢包环境的编码策略不清楚CABAC的上下文建模就没法解释为什么某些场景下熵编码的性能上不去。笔试不考这些反而考奇怪的东西那才是真的奇怪。所以这套卷子的逻辑其实很简单用专业题验证你懂不懂编解码用算法题验证你写不写得来代码简答题验证你能不能把复杂的原理讲清楚。三个维度看完一个候选人的水平基本就清楚了。2. 核心考点拆解H.264/H.265高频知识点逐项过线2.1 I帧、P帧、B帧与GOP结构这套卷子的简答题几乎必有一道关于帧类型和GOP结构的题。选择题里也经常出现“下列哪项关于B帧的描述正确”这种变体。先说基础概念。I帧是帧内编码帧只利用当前帧自身的空间冗余压缩不参考其他帧可以理解为视频里的“关键帧”解码时可以直接重建完整画面。P帧是前向预测编码帧参考已解码的过去的帧做预测只编码残差和运动矢量压缩效率比I帧高很多。B帧是双向预测编码帧参考前后两个方向的已解码帧压缩率在三种帧里最高但代价是编码复杂度更高、解码缓存更大。笔试里常挖的坑是B帧的编解码顺序和显示顺序的关系。因为B帧要参考未来的帧所以编码端必须先把后面的参考帧编码完再回头编码B帧。这就导致码流里的帧顺序和播放顺序不一致需要通过POCPicture Order Count来标记显示顺序。很多人在简答题里把这个讲反了丢分很可惜。GOPGroup of Pictures是一组连续的画面结构可以表示为I B B P B B P ... I。GOP有两个重要参数GOP长度和IDR帧。IDR帧是特殊的I帧作用是强制刷新参考帧列表保证从这个帧开始解码端可以完全独立解码。笔试中常问GOP越长码率越低还是越高答案是GOP长意味着I帧间隔大单位时间里I帧数量少整体码率通常更低但编码容错性差网络丢包后要等下一个IDR才能恢复画面。这也是直播场景为什么倾向于短GOP甚至全I帧的原因。我实操中的经验是GOP的选择要结合具体的传输协议和丢包率来定。点播场景GOP长度常见的是250帧左右直播场景一般控制在1到2秒也就是30到60帧。丢包严重的弱网环境宁可多花码率多放I帧也要缩短画面恢复时间。这道题要答得高分除了定义还需要写出这层工程权衡。2.2 块划分与预测编码从宏块到CTUH.264时代最小处理单元是宏块16x16像素。H.265引入CTUCoding Tree Unit概念默认大小64x64可以递归划分成更小的CUCoding Unit。笔试里经常用一个具体例子来考一个64x64的CTU按四叉树递归划分最深到8x8问共有多少种划分方式。这个题考的不是那棵树长什么样而是你是否真正理解编码器为什么要做这种划分。答案其实在“内容自适应”这四个字里。平坦区域适合大块编码一个16x16甚至64x64的块就能用极低码率表示纹理复杂的区域必须切成小块逐块选择预测模式才能把残差降到最低。如果视频编码不划分块全图都用固定尺寸要么平坦区域浪费码率要么复杂区域质量崩掉。这种“图像内容驱动编码决策”的思想是本套卷子反复出现的主题。帧内预测是拿已经编码好的相邻像素按照不同的方向去推测当前块的像素值。H.264的亮度帧内预测有9种模式H.265扩展到了35种包含Planar、DC和33种角度模式。帧间预测则是参考其他帧的画面用运动矢量表示“画面从哪移到哪”编码Motion Vector的残差和像素残差。运动搜索的匹配准则常用SAD绝对差和或SATDHadamard变换后的绝对差和笔试里编程题很可能就是让你手写一个SAD计算函数。我刚入门时犯过个错误以为块划分和预测模式是“哪个好选哪个”后来读了HM参考代码才知道编码器是用率失真代价函数来统一决策的把你候选模式和块尺寸的编码失真加上码率代价算出一个综合代价取最小值。这个问题在2.4里会展开。2.3 变换、量化与熵编码数据压缩的三个台阶预测做完产生残差残差本身还是像素空间的数据直接编码效率很低。编解码系统里随后要做三件事变换、量化、熵编码。笔试的简答和选择题都会在这里出题。变换的作用是去相关性。残差块里相邻像素往往还有较强的相关性通过DCT变换把空间域的像素值变成频率域的系数。能量集中在低频区域高频系数普遍很小甚至接近0。编码端对变换系数做量化把小的系数变成0从而大幅减少需要编码的非零系数数量这是压缩率提升的关键。H.264和H.265实际用的是整数DCT是为了避免浮点运算带来的平台不一致问题和精度损失。量化是一个有损过程它决定了质量和码率的平衡点。笔试常考QP和量化步长的关系H.264中QP每增加6量化步长大约翻倍码率大约减半。具体公式是 Qstep 2^((QP-4)/6)这个考点很经典。QP取值范围0到51QP0量化最精细画质最高QP51量化最粗糙画质最差。我见过很多人把这个关系记反以为QP大是画质好这要特别注意。熵编码做的是无损压缩把量化后的系数和语法元素进一步压紧。H.264支持CAVLC和CABAC两种熵编码方式。CABAC因为使用上下文建模和自适应算术编码压缩率比CAVLC高10%到15%但复杂度也更高。H.265和更晚的编码标准基本都以算术编码为主。笔试里如果问“为什么CABAC压缩率更高”核心答案是它根据已编码符号的概率动态调整码率分配而不是给每个符号固定的码长。这里有一个非常好的生活类比变换类比成把一句话里重复出现的词汇找出来量化类比成把“非常非常非常非常高兴”简化成“非常高兴”熵编码再根据高兴这个词出现频率高给它编一个更短的码字。每一步做一件事环环相扣。2.4 码率控制与率失真优化编码器的“经济学决策”简答题里最可能压轴的是率失真优化。这也是整套卷子里最考理解深度的一道题因为它不是一个孤立知识点而是编解码器做所有决策的总原则。编码器的每一次决策——选哪种帧内预测模式、用多大的块、采用什么运动矢量、甚至要不要把某个系数编码成0——本质上都是一笔经济账。画质越好需要的码率越高但码率又是受限资源。怎么平衡传统做法是拉格朗日代价函数J D λ × R其中D是失真通常用SSE或SAD来度量R是编码消耗的比特数λ是拉格朗日乘子。决策目标是在所有候选方案中选择让J最小的那一个。λ越大码率权重越高编码器倾向于选择消耗比特少的方案比如用更大的块、更少的预测模式λ越小失真权重越高编码器愿意花更多比特去提升画质。λ和QP是强相关的。H.264参考模型里 λ 0.85 × 2^((QP - 12)/3)实际编码器会根据帧类型和编码状态做修正。笔试里不可能让你现场推导这个公式但会问“QP增大时λ怎么变”“码率控制为什么需要根据内容调整参数”这类问题。能回答到位的前提是理解编码器在做“给定码率下失真最小”的约束优化问题。但要注意一点实际工程落地和理论模型并不完全一致。我在项目里调x265时发现真实码控会综合考虑I/P/B帧权重、虚拟缓冲区占用度、场景切换检测等多种因素。理论模型解决的是“单一帧里怎么选”工程码控解决的是“一段时间内码率怎么分配”。笔试里最好把这两层都答出来第一层是率失真代价函数如何影响帧级和块级决策第二层是码控如何在GOP和序列级别分配码率预算。这样答出来的简答题阅卷人一看就知道你不仅背了公式还考虑过工程实现。码率控制方式也是常考点。同样是控制输出码率CBR适合实时通话场景带宽固定且不允许出现大的码率波动VBR适合点播场景允许画面复杂时多消耗码率画面简单时少消耗码率整体平均码率受控ABR是平均码率控制介于CBR和VBR之间CRF是x264/x265里很常用的固定质量模式它不直接控制码率而是通过固定QP偏移来维持相对稳定的感知质量。考场上要是能把CRF和CBR/VBR的差异讲明白基本就把这块分数拿稳了。3. 算法与编程题实操从思路到代码3.1 经典数据结构与算法题基本功要练到肌肉记忆这套卷子的编程题部分第一道通常是经典算法。从欢聚时代这类公司出题的风格看考核重点集中在排序、二分查找、字符串匹配、链表操作这几个方向。KMP是高频中的高频因为视频编解码里大量用到模式匹配和搜索的思想而且KMP的next数组推导过程能把“懂原理”和“背代码”严格区分开。我记得当时卷子里有一道KMP的题给一个模式串要求写next数组并手写匹配过程。很多人在next数组定义上栽了跟头——next[i]到底表示最长相等前后缀长度还是表示失配后跳转的位置。不同教材定义不一致有的定义为最长相等前后缀长度有的定义为最长的前缀等于后缀的长度再减一。我建议笔试时如果题目没有明确说明就按最常见的定义但要写清楚自己的约定。在代码里用注释标出“这里next[i]表示前i个字符的最长相同前后缀长度”阅卷人一看就明白。快速排序也是高频题但一般不满足于让你写个基本的递归版本。出题人可能会加条件数据量很大、内存受限怎么办这时候不能原地快排得考虑外部排序。还有可能让你分析快排在已经有序的输入下时间复杂度退化为O(n^2)的原因以及如何通过随机化选主键避免退化。这类题考察的是算法理解和边界情况处理能力比单纯默写代码要求更高。二分查找看起来简单实际考细节。比如边界条件是left right还是left rightmid取上取整还是下取整都会影响死循环。我记得当时一道题是在排序数组中找目标值的左右边界很多人会用两次二分写但边界条件处理不对导致第一次返回的left可能不是目标值的第一个索引。手写代码时遇到这类题先把终止条件和收窄策略写清楚再往下写代码正确率会高很多。我备考时的经验是经典算法每周手写一遍不要只看思路、用IDE补全。考场环境没有智能提示也没有编译检查写出来的代码语法错误少、边界完整、变量命名清晰这些实实在在的编码习惯比多背几道题有价值。3.2 视频编解码场景下的算法题把公式变成可运行代码如果说经典算法是基础分那视频编解码相关的编程题就是这套卷子和普通软件岗笔试拉开距离的地方。我印象里这类题目的思路是把编解码器里的某个模块抽象成一道独立的算法题。最典型的是计算两个像素块的SAD。函数输入是两个N x N或M x N的数组输出是绝对差之和。听着很简单但有几个坑。第一个坑是嵌套循环的索引顺序内存布局是行优先所以外层循环应该遍历行内层遍历列否则缓存命中率很差。第二个坑是数据溢出SAD的累加结果可能超过int8的范围需要根据块大小选择signed int甚至更大的类型。第三个坑是提前退出如果用SAD做运动搜索很多情况下不需要算完整个块就能判断它不是最优候选可以在循环里累计diff后判断是否超过当前最小SAD超过就跳出。这个优化在参考软件和商业编码器里都有用到笔试卷子上能写出这个思路非常加分。还有一种常考题型是运动搜索。给一个当前块、一个参考帧搜索窗口要求找一个运动矢量让SAD最小。朴素的穷举搜索很容易写但复杂度高。出题人会问问你怎么加速。这时候把三步搜索、菱形搜索、六边形搜索的思路讲清楚就行不要求完整实现。核心思想是先粗后细、由远及近在搜索中心用一个较大的步长试探多个方向每次朝SAD最小的方向收拢步长直到步长为1。这和爬山法很像容易陷入局部最优所以实际编码器里会用多起点搜索来缓解。YUV到RGB的转换也出现过。YUV420是视频领域最常见的采样格式每4个Y像素对应一组U和V。转换时要注意边界情况图像宽高可能是奇数UV分量是Y的1/4索引计算很容易写错。公式虽然各标准有差异但核心是 Y 0.299R 0.587G 0.114B 这条亮度公式的逆变换。笔试遇到这个题关键是先把采样布局图画出来再写转换函数不要在脑子里硬算UV的下标。3.3 手写代码的踩坑记录考场环境下的生存指南当时我身边的同学不少人栽在编程题上不是不会做而是写出来的代码跑不通或者看着别扭。我总结几个考场环境下特别容易踩的坑。第一边界条件判断缺失。比如SAD函数里访问像素块索引时没有判断块是否超出图像边界。视频编码算法的大量代码都涉及边界处理H.264和H.265里专门有边界填充Padding模块来处理这个问题。笔试时哪怕是纯算法的SAD计算也要在函数开头检查输入合法性在图像边界场景下说明如何处理越界像素。面试官看到这种考虑好感度会明显上升。第二整数类型选错。视频像素值是0到255的uint8_t但计算差值和梯度时结果可能为负必须用signed类型。累加SAD时比如一个64x64的块理论最大SAD是64×64×255约104万超过uint16_t范围需要用int甚至更大的类型。很多人栽在这个细节上代码逻辑对但结果错非常可惜。第三变量命名和注释缺失。手写代码的卷面分是真实存在的。面试官一天看几十份卷子代码里全是a、b、c这种命名印象分直接掉一档。我当时习惯用sad、best_mv、ref_idx这种有语义的命名关键逻辑简单注释一下最后留出一块空间写“算法复杂度分析”和“优化思路”。哪怕代码有小瑕疵这种答题方式也会传递出“这个人平时写代码是有章法的”的信号。编程题不是背答案而是展示你的工程思维。写一个运动搜索函数时如果能提到“实际编码器里会结合预搜索和亚像素精度”说明你对编解码器的实操有过思考。这对校招候选人来说是很重要的加分项。4. 常见问题与备考复盘从考场实战到踩坑记录4.1 考场高频失误这些都是真实发生过的把我和几位考过类似题目同学的经历汇总起来高频失误大概集中在下面几个点每一个都是真实发生过的。第一个失误是把显示顺序和编码顺序搞混。卷子里给出一组I B B P的帧要求重排出码流顺序不少同学直接在答题纸上写了I B B P结果应该是I P B B。要理解B帧需要未来参考帧先编码这个顺序问题在H.264/H.265里是基本常识却是丢了最多分的地方。我自己的经验是现场遇到这类题先在草稿纸上画出参考箭头再依次把每个帧的编码顺序标出来最后誊写到答题纸上基本不会错。第二个失误是概念混淆。比如把熵编码、DCT变换、帧内预测这几种语义混在一起说没有清晰的分层。编解码链路是先预测产生残差再变换去相关再量化去精度最后熵编码去冗余。每一层解决不同的问题各层的目标对象也不同。答题时建议按步骤拆开写每一步用一到两句话概括目的和手段阅卷人扫一眼就知道你脑子里有完整的知识框架。第三个失误是算法题不做复杂度和优化分析。比如写出一个SAD计算函数只用三重循环没有讨论可以做的缓存优化、SIMD向量化、提前退出机制。笔试答题时时间和空间受限但面试官真正想看的是这些扩展点。我当时在每道算法题的末尾都补了“该算法的时间复杂度是O(n^2)可以通过XXX优化到O(nlogn)”这种分析这不是画蛇添足而是展示工程优化意识。4.2 视频编解码知识自查表考前快速过一遍结合这套卷子的考点我整理了一份考前自查表。如果你准备参加音视频岗笔试下面这几条可以在考前48小时快速过一遍考点自查问题答不上来时的资料方向YUV采样4:2:0的U/V分量大小是Y的几分之几颜色空间入门文章帧类型B帧参考顺序与显示顺序为什么不同H.264标准章节8.1GOPIDR帧和普通I帧区别是什么H.264标准章节7.4.2.4变换整数DCT相比浮点DCT有什么好处视频编码全角度详解量化QP增加6量化步长变化几倍新一代视频压缩编码标准熵编码CABAC为什么比CAVLC压缩率更高算术编码入门资料预测H.265帧内预测有几种亮度模式H.265标准概览运动估计SAD和SATD在什么场景下更好编码器参考软件源码率失真优化J D λR中λ增大会选码率更高还是更低的方案率失真优化论文综述码率控制CRF和CBR的本质区别是什么x265文档去块滤波边界强度BS在什么条件下为0、1、2H.264标准章节8.7SAOH.265引入SAO是为了解决什么问题H.265标准概览这张表不用逐条背诵只需要能做到看到考点后能在30秒内用自己的话解释清楚原理并且能举出一个实际编码器里的例子。做到这一步笔试简答题基本不会丢大分。4.3 我的备考经验与建议从笔试到入行复盘这次笔试我最大的体会是备考不只是背知识点更要亲手“摸”一遍编码器。只看书不看代码很多概念永远是空中楼阁。我当时花了几个晚上做了这么几件事性价比非常高也推荐给正在准备的朋友。第一用FFmpeg命令行把一段视频转成H.264和H.265然后用ffprobe查看码流信息观察I帧和P帧的大小差异。随便找一段视频执行ffprobe -show_frames input.mp4能看到每个帧的类型、大小、PTS/DTS。把输出拉到表格里统计一下就知道I帧比周围P帧大很多倍B帧一般是最小的。这个操作十分钟就能完成但让你对帧大小差异的印象直接扎根。第二找一个码流分析工具看NAL单元结构。H.264的码流由NAL单元组成每个单元头部的nal_unit_type字段标识类型1是非IDR的slice5是IDR帧slice7是SPS8是PPS。自己能识别这些笔试选择题里关于码流结构的题就完全不是问题了。也可以尝试用简单脚本解析一个视频文件手动找SPS和PPS的起始码这会让你对“码流”这个概念从抽象变具体效果远好于背十遍标准文档。第三调一次x264或x265的参数对比不同CRF下的输出码率和PSNR。用x265 --crf 20压一遍再用--crf 30压一遍看看码率差多少画质差多少理解CRF这个参数到底在控制什么。你甚至可以用ffmpeg的psnr滤镜输出两段视频的PSNR对比把感知画质和客观指标对应起来这个经验在笔试和面试里都能成为加分谈资。第四有条件的话读一下HM或VTM参考软件的代码片段。不用全读只需要看帧内预测的模式决策函数和运动估计的搜索函数。你会发现代码里大量使用的是率失真代价计算这和笔试简答题要考察的‘编码器如何做决策’是直接对应的。哪怕只读几百行对整个编码器的运作方式都会有质的飞跃。我个人在实际操作中的体会是校招笔试可以靠短期刷题拿到及格分但想拿高分取决于你平时是否真正探索过编码器内部的工作机制。这套卷子的考察逻辑相当清晰——它要的不是背答案的人而是对视频编解码链路真正有手感的人。60%的知识点可以从书上找到答案剩下40%需要你动手调过参数、翻过源码、踩过实际的坑才能答出来。最后再分享一个我用过的小技巧考前不要只刷算法题也不要只背视频知识点而是两者交替进行。每次在LeetCode上刷完一道题就转过头用编码器的知识来解释这道算法为什么在这个场景下会这样设计。比如刷完KMP想一想运动搜索里的匹配思想刷完二分查找想一想码率控制里如何寻找最优QP。这种串行联想复习下来考点不仅记得牢还能在笔试的综合题里自然用上。这套方法直到今天也还在帮我在面试候选人的时候一眼看出哪些人是真的理解视频编解码哪些人只是背了两个月面试题。
返回列表