2018年那会儿,网易这套实习生笔试题在圈子里流传得挺广,不光是冲着网易去的同学会刷一遍,很多准备音视频岗位面试的人都会拿它当试金石。我当时也看过这套题,印象最深的是它不考“你用过什么工具”,而是把一堆协议层的东西铺开,让你在纸面上推演。这跟很多人对“开发岗笔试”的预期不一样——以为会考FFmpeg命令、考API调用,结果卷子上一大半是H.264的NALU类型、B帧参考关系、时间戳同步这类原理题。
把这套题掰开揉碎之后,你会发现它其实在说一件事:视频编解码这个岗位,招的不是熟练工,而是底子扎实、能看懂协议、能理解硬件行为的人。这篇文章我就以这套笔试为引子,把题目背后真正想考察的知识点拆开讲一遍,最后再聊到rk3588这类硬件平台,看看从笔试到真实项目到底有多远。
1. 这道笔试到底在筛选什么样的人
1.1 岗位画像:实习生不是用来干活的,是用来培养的
网易当年做音视频的摊子铺得很大,云音乐要处理音频编解码和网络传输,云信要给IM做实时音视频通话,CC直播要解决推流、转码、低延迟播放。这几个业务线对视频编解码人才的需求是同一个逻辑:要有人能看懂码流结构,能定位花屏、卡顿、音画不同步的问题,能在硬件编解码器和开源方案之间做取舍。
但实习生这个层级,没人指望你上来就能改x264的码率控制,也没人指望你能独立调通一条硬编链路。笔试的定位是筛选“有没有在这个领域长期积累的潜力”。所以你会发现这套题目的风格很“学院派”——基础理论、协议结构、数学原理占大头,工具链知识反而少。这说明命题人想找的是那种拆开一个MP4文件不会慌、看到SPS/PPS能说出含义、理解GOP为什么是50的人。
1.2 命题的三个层次:协议、工程、思维
把整套题看下来,基本可以分成三个层次。
第一层是协议基础,比如H.264的NALU类型怎么区分、SPS和PPS各自存什么、I/P/B帧各自有什么作用、GOP长度会影响什么。这一层考的是“你知不知道编码器在干什么”。
第二层是工程细节,比如YUV420和NV12的内存排布有什么不同、DTS和PTS的区别是什么、音视频同步有哪几种策略、封装格式里的关键帧索引怎么组织。这一层考的是“你能不能跟播放器、跟渲染器、跟硬件对接”。
第三层是思维深度,比如码率控制算法在CBR和VBR之间如何取舍、去块滤波的作用是什么、如何判断一个卡顿是网络问题还是解码性能问题。这一层考的是“遇到问题时你会不会排查、会不会做技术选型”。
三层下来,基本就把“会用”和“懂行”区分开了。我当时批过类似的卷子,很多人第一层能拿满分,第二层开始掉链子,第三层基本上空白。这个分布其实很真实——学校教了多少、自己钻了多少,一测就出来。
1.3 这套卷子的整体节奏
如果按题目类型划分,这套笔试题大概有下面几类:
- 概念题:H.264与H.265的差异、帧类型判断、参考帧的作用
- 计算题:码率与文件大小的换算、GOP大小与I帧间隔的关系
- 流程题:解码器的完整工作流程、推流拉流的主要环节
- 场景题:花屏、卡顿、音画不同步,各自优先排查什么
比重上,概念题和流程题占了大头,场景题是拉分项。这说明笔试不是想难倒你,而是想看看你对这个领域有没有“感觉”。有感觉的人看到场景题会自然地往协议、缓冲、时间戳这些方向想,没感觉的人只会写“可能是网络不好”。
2. 从一道真题看编解码基础理论的分量
2.1 H.264/H.265的编码骨架
如果没有意外,这套卷子的第一道大题多半会落到H.264的编码框架上,因为它决定了后面所有题目的语境。H.264的核心思路是混合编码:空间上用帧内预测去掉图像内部的冗余,时间上用帧间预测去掉帧与帧之间的冗余,然后对残差做变换、量化、熵编码。
笔试里常考的是把这条链路按顺序写出来,或者给几个步骤让你排序。有一次我看到一个同学的答案是“量化→变换→预测→熵编码”,把变换和量化换了位。这个错误非常典型,因为很多人背流程的时候只记名词,不理解为什么先变换再量化。实际上,变换是把像素域的残差转换到频率域,让能量集中到低频系数上,量化才是真正丢信息的那一步。先量化再变换的话,量化引入的误差会被变换放大,重建质量会明显变差。
H.265在这个框架上做的主要是两件事:一是把宏块扩展成更大范围可选的编码树单元(CTU),让大块平整区域用更少的比特表示;二是增加了更多帧内预测方向和更灵活的参考帧管理。笔试如果问你“H.265相比H.264为什么能省一半码率”,答案颗粒度不能停在“算法更先进”,要落到具体机制上:更精细的帧内预测、更灵活的块划分、更高效的变换和熵编码。
2.2 I/P/B帧与GOP结构,必须答到参考关系这一层
帧类型这张牌,基本是视频编解码笔试的必考题。大多数人的认知止步于“I帧是关键帧,P帧是预测帧,B帧是双向预测帧”,但这个答案在网易这套题里只能拿一半分。真正能拉开差距的是下面几个层次:
第一层,I帧可以不依赖任何其他帧独立解码,所以它是随机接入点,也是GOP的起点。第二层,P帧参考前面的帧,可以是I帧也可以是其他P帧,所以参考帧的管理不是简单“参照上一帧”。第三层,B帧同时参考前向和后向的帧,这带来一个反直觉的结果:B帧的显示顺序和解码顺序不一致。
笔试经常给出一串帧的编码顺序,让你写出显示顺序,或者反过来。这题难倒过很多人,因为它需要你理解解码器必须先把B帧的后向参考帧解码出来,才能解码B帧。所以码流里的帧顺序是“I P B B P”这样的排列,而显示时又要按PTS重新排回“I B B P”。不理解这一层的人,遇到多B帧的情况基本就乱了。
GOP结构的考察点则在于I帧间隔。GOP越短,随机接入越方便,但码率越高;GOP越长,压缩效率越好,但遇到丢包时错误扩散的范围也越大。网易那道题我记得是分析一个GOP为50的场景,丢了一个P帧后面的帧会花到什么程度。答案不是“全部花掉”,而是要看这个P帧有没有被后续帧参考。如果它只是被邻近几个帧参考,错误扩散到下一个IDR帧之前就会终止。这个分析过程考察的就是对参考链路的理解,而不是死记硬背。
2.3 关于SPS/PPS和NALU的考察
H.264的码流由NALU组成,其中SPS和PPS是非常容易考的概念。SPS存的是分辨率、帧率、参考帧数量这些序列级参数,PPS存的是熵编码模式、片组映射这些图像级参数。它们之间的关系可以类比为:SPS是全局配置,PPS是单张图像的配置。
笔试题的常见变形是给你一段十六进制的NALU头,让你判断它是什么类型。NALU头的一个字节里,低5位就是类型值:1是非IDR的片,5是IDR片,7是SPS,8是PPS。这个知识点本身不难,但很多人只记类型编号不记背后的结构。我建议准备笔试时把这个知识点跟实际抓包结合起来理解——用工具打开一个H.264裸流,你会看到每个关键帧前面都跟着SPS和PPS,这就是解码器初始化的依据。没抓到SPS/PPS直接给片数据,解码器无从下手,这在RTP推流场景里是一个真实存在的坑。
3. 工程落地方向:解码器结构、像素格式、封装与同步
3.1 解码流程:笔试填空题背后是一条流水线
解码器的工作流程也是这套卷子的常客,而且通常用填空题或排序题来出:从码流中提取NALU→解析SPS/PPS→对片数据进行熵解码→反量化→反变换→帧内/帧间预测补偿→去块滤波→输出YUV帧。
这个流程看起来是死记硬背,实际上每一步都对应一个真实的问题域。比如“熵解码拿到的是什么”,答案是量化后的变换系数和运动矢量;“反量化为什么会有精度损失”,因为量化步长本身就是有损的;“去块滤波为什么放在最后而不是放在预测之前”,因为滤波要基于重建帧来做,顺序反了会导致环路漂移。
帧内预测这一步值得多说一点。H.264的帧内预测有9种方向模式,核心思路是用周围已重建像素去预测当前块,然后只编码残差。笔试会问你“为什么帧内预测用的是重建像素而不是原始像素”,答案是为了保证编码端和解码端的预测一致。如果用原始像素做预测,解码端拿不到原始像素,两边预测不一致,误差会累积。这个细节能看出一个人有没有真正跑通过编码器。
3.2 像素格式:从YUV420到NV12/NV21
视频编解码离不开像素格式,尤其是YUV家族。笔试常考的是YUV420为什么比RGB444省一半存储,以及NV12和NV21的区别。
YUV420的意思是:亮度Y每个像素都保留,色度U和V每四个像素共享一对,也就是水平方向各采样一半、垂直方向各采样一半。一个1920x1080的帧,Y分量是1920x1080个字节,U和V各是960x540个字节,总共是1920x1080x1.5个字节。相比RGB888的1920x1080x3个字节,正好省一半。
NV12和NV21的区别在于UV的排列顺序:NV12是UV交错、U在前;NV21是VU交错、V在前。这个在Android平台和rk3588的硬件编解码器上特别重要,因为不同硬件模块默认输出的格式不一样。rk3588的VPU解码输出通常是NV12,但如果你要在OpenGL里做渲染,可能需要转成RGBA,或者直接在shader里处理NV12的两个plane。笔试不会考到这么细,但会问“NV12和I420的区别”,实际上就是UV是交错排列还是分开排列。
这题丢分的人不少,因为平时写代码直接调接口,格式转换都封装好了,很少有人会关注内存布局。但做视频开发,格式转换是最容易踩坑的地方——分辨率对了、格式不对,画面就是绿油油一片或者颜色错乱。
3.3 DTS/PTS与音视频同步:场景题的重灾区
时间戳是笔试和面试都绕不开的点。DTS是解码时间戳,PTS是显示时间戳。在有B帧的视频流里,两者的顺序不同;在音频流里,因为不存在B帧,两者通常相同。
笔试的出题方式一般是:给你一组视频帧的PTS和DTS,问播放器应该按哪个时间戳排显示顺序。答案是PTS。解码器按DTS顺序解码,但视频渲染必须按PTS顺序把帧交到屏幕上。如果直接按DTS显示,B帧就会在时间轴上乱掉,画面会出现“倒放”一样的诡异效果。
音视频同步是场景题的重头。常见的同步策略有三种:以音频为主时钟、以视频为主时钟、以外部时钟为主时钟。实际产品里绝大多数选择以音频为主时钟,因为人耳对音频卡顿更敏感,而视觉可以容忍一定程度的丢帧或重复帧。答题的时候如果能补充一句“要定期校准主时钟,因为晶振漂移会导致长时间播放后累积偏差”,这个答案的含金量会明显上一个台阶。
网易那套题里有一道场景题,说的是播放一段时间后音画开始不同步,让你列出排查思路。合理的链路是:先看时间戳在源头是否正常生成,再看网络传输是否引入抖动,然后看解码器的缓冲策略是否丢弃了过多数据,最后看渲染环节是否有重复帧。每一步背后都有对应的工具和日志,能写出这条链路的人,看问题的方式已经是工程化的了。
4. 码率控制与画质优化:面试官真正想听到的回答
4.1 码率控制算法怎么答才不会显得外行
码率控制是最容易考到、也最容易答得空泛的主题。如果你只写“CBR是固定码率,VBR是可变码率”,那基本只能拿基础分。这道题想听到的是你理解两种模式各自的适用场景和代价。
CBR(固定码率)适合带宽受限的场景,比如直播推流、视频会议,它的特点是输出码率稳定,但代价是画面复杂度高时质量下降,复杂度低时浪费码率。VBR(可变码率)适合存储类场景,比如点播文件的离线转码,它允许在复杂场景多用码率,在简单场景少用,所以在同等平均码率下画质更好,但峰值码率可能很高,不适合实时传输。
中间还有一个ABR(平均码率),它试图在两者之间找平衡:允许短期码率波动,但长期平均保持稳定。这个在直播平台经常用作“目标码率+上下限约束”的实现方式。
答题时如果能补充一句“码率控制本质上是一个比特分配问题,难点在于如何预估当前帧的复杂度”,这个理解高度就出来了。框架层面,x264和x265都是通过调节量化参数(QP)来控制输出码率,QP越大细节丢得越多、码率越低。恒定质量模式(CRF)就是固定一个目标QP让编码器自己浮动码率;而ABR模式则是通过反馈控制不断调整QP来逼近目标码率。
4.2 码率、分辨率、帧率的关系,记一个快速估算公式
笔试计算题里常出现“一个1080p30的视频,码率4Mbps,录1小时有多大”这类题。计算方式不复杂:4Mbps = 4,000,000 bps,换算成字节要除以8,得500,000 B/s,一小时就是500,000 x 3600 = 1.8GB。如果用MB来算,大约是1716MB,也就是1.68GiB。
这里有个坑:视频领域经常混用Mbps和MB/s,题干给的是Mbps,算文件大小必须先除8再乘时间。不少人在这里把十进制和二进制又搅和一遍,算出来差好几个百分点。
反向的题目也常出:给你一个文件大小和时长,反推平均码率。这个思路要记住一个公式:码率(kbps) = 文件大小(KB) x 8 / 时长(秒)。如果算出来码率高得离谱,那播放时大概率会卡顿,因为实际网络带宽跟不上;码率太低,画质又会明显下降。
对于H.264,业界有一个粗糙的经验值:1080p视频,中高画质大概需要4-8Mbps;720p大概2-4Mbps。H.265可以在这个基础上省一半左右。笔试问到“为什么同样的码率H.265画质更好”,答案要落到编码效率上,而不是简单地“算法更先进”。H.265以更细的块划分和更灵活的运动补偿为代价,换来了更高的压缩率,代价是编码复杂度翻了几倍。
4.3 客观指标与主观画质,如何向面试官展示调优思维
画质评价通常分客观和主观两条路。客观指标里最常见的是PSNR和SSIM。PSNR基于像素级的均方误差,数值越高说明失真越小,但它的缺陷在于对人眼感知不友好——有些PSNR很高的图像看起来反而比PSNR稍低的更“脏”。SSIM则从亮度、对比度、结构三个维度计算相似度,比PSNR更贴近主观感受。
面试如果聊到画质优化,最好的回答是给一个具体场景。比如直播场景中,运动剧烈画面和人脸特写的码率分配策略就应该不同:人脸区域值得多分一点码率,因为人对人脸细节很敏感;静止背景可以大胆用较大的QP。这种“根据内容特性分配比特”的思路,比强调“我调了很多参数”有说服力得多。
笔试不太可能让你现场调编码器,但它可能给你一组不同QP下的文件大小和PSNR,让你分析趋势。这时候要能说出:QP从20提到40,文件大小指数级下降,但PSNR不会线性下降,因为自然图像的能量集中在低频,量化掉高频分量对主观观感的影响可能小于码率省下来的收益。能说出这一层,说明你不是单纯背概念,而是理解率失真优化的基本逻辑。
5. 从笔试题到rk3588:硬件编解码时代的变化
5.1 这套笔试题里的知识,在rk3588上全都用得着
rk3588是瑞芯微的旗舰平台,视频编解码能力很突出:支持8K@60fps的H.265/VP9/AVS2解码、8K@30fps的H.265/H.264编码。这个能力在嵌入式平台上算天花板级别了,所以很多人拿到RK3588的开发板第一件事就是测它的编解码性能。
有意思的是,如果拿着2018年网易那套笔试题去对照rk3588的开发过程,你会发现题目里的概念几乎每个都会用到。比如你调用MPP库解码一个8K视频时,你先要解析的还是SPS/PPS;你需要确认解码输出的像素格式是NV12还是NV21;你往编码器喂帧的时候,还是要根据PTS决定显示节奏。协议的东西不会因为硬件换代就失效,变化的只是实现方式。
5.2 硬编解与软编解的差异,笔试不会明说但面试会问
笔试可能会问“什么是硬解码、什么是软解码”,但面试往往会追问“你们项目里为什么选硬解不选软解”。
软解是用CPU跑开源库,比如FFmpeg配合libx264/libx265,优点是灵活、更新快、参数可控,缺点是CPU占用高、功耗大。硬解是用芯片里专用的编解码单元(VPU)处理,优点是速度快、功耗低、CPU几乎不参与,缺点是格式支持取决于硬件,而且参数调节空间小。
在实际项目中做选型时,核心就一句话:“如果你的平台对功耗和实时性有要求,优先硬编解;如果你的产品需要频繁更新编码算法或者做实验性调优,直接用软件方案。”rk3588上跑8K视频,软解基本是不现实的,CPU会直接被吃掉一大半;硬解则可以做到几十毫秒解一帧,CPU占用很低。
还有一个常见考点是“硬解和软解的解码结果有什么不同”。实际上两者的输出都是YUV帧,理论上应该一致,但因为去块滤波、参考帧管理等细节实现有差异,硬解和软解在同一码流上可能产生极细微的像素差异,这个在正常使用中感知不到。真正需要注意的差异是,硬解对码流的容错能力通常弱于软解,遇到格式不规范、SPS参数怪异的码流,软解可能还能出图,硬解很可能直接报错或者黑屏。
5.3 MPP库基本流程,理解原理后很好上手
rk3588的硬件编解码离不开Rockchip的MPP库。它的基本流程是这样的:先创建上下文(MppCtx),再配置解码/编码参数(比如分辨率、格式、码率模式),然后循环地往输入队列里丢数据包、从输出队列里取帧。
解码侧的关键是理解“输入包与输出帧不是一一对应”这件事。因为存在B帧重排,而且解码器内部会有缓冲,你喂进去三四个数据包可能才出来一帧,或者一个数据包解出多帧。如果按照“喂一包收一帧”的同步思维去写,很容易卡死。
编码侧的关键是设置好GOP和码率控制参数。rk3588的MPP支持CBR和VBR模式,对实时流场景一般用CBR并设置一个合理的码率;对录制场景可以考虑VBR来保画质。另一个容易出问题的是帧率控制——如果你没有按实际帧率喂帧,编码器生成的码流时间戳就会乱,播放器会出现快放慢放。
我见过很多人拿到rk3588开发板后,直接把官方demo里的GOP和码率参数原样用,结果在直播推流时频繁花屏。原因就是那个demo是为本地录制设计的,GOP很大、码率控得很准,但网络传输遇到丢包时错误扩散范围太大。把GOP调短到比如两秒一个IDR帧,同时把码率冗余留出10%-20%,花屏概率会大幅下降。这里面的分析思路,跟前面讲的GOP长度对错误扩散的影响完全一样——笔试里的概念在实战里直接变成了一个可执行的调优手段。
5.4 从纸面到真机:时间戳和像素格式依然是翻车重灾区
最后说一个我在rk3588平台上的真实经历。有一次做8K视频解码显示,画面出来了,但颜色明显发绿,且偶发性音画不同步。排查后发现是两个独立的坑叠加在一起。
颜色发绿是因为GPU渲染时把NV12的两个plane当成了连续内存处理,但MPP解码输出时Y平面和UV平面之间的stride不连续,导致UV数据读错了位置。解决办法是先获取drm buffer的信息,按正确的offset和stride去映射显存,而不是想当然地按宽度乘高度算偏移。
音画不同步是因为我在丢帧策略上做了“解码丢帧”,但音频还在按原始PTS播放。解码丢帧会改变视频帧的显示节奏,后续所有帧的PTS对不上音频,偏差会越来越大。后来改成“渲染丢帧”,也就是解码照常进行,但在显示前判断是否逾期,只丢赶不上显示时间的帧,同步就恢复了。
这两个问题,单看任何一个,都可以回到2018年那套笔试题的知识点上:像素格式决定你怎么处理解码输出,时间戳决定你如何做同步。只不过笔试考的是概念,真机调的是bug。
我的经验是,准备这类笔试时不要只刷题,最好手头有一套能跑的编解码环境。哪怕是拿FFmpeg命令行做实验,把一段视频分别用不同GOP、不同码率转码,再对比输出文件的大小和播放体验,你对“GOP影响什么、码率影响什么”的理解都会比死记硬背深得多。等你拿到rk3588这类硬件平台时,再用MPP库的example跑一遍解码、编码、显示全链路,笔试里那些名词就真的变成了你手里的工具。