解码是将压缩媒体流转换为适合屏幕和扬声器输出的未压缩格式的过程。在移动设备上,解码要么通过CPU以软件方式执行,要么通过GPU和DSP的专用硬件模块执行。根据MDN Web Docs(2026)的数据,现代编解码器将流压缩100–500倍,而解码在正确选择压缩配置文件的情况下可以无损地恢复原始质量。
要点
解码是将压缩的数字数据恢复为原始未压缩格式的过程。在媒体领域,解码从编码器创建的压缩比特流中恢复视频帧。没有解码,用户就无法看到视频或听到音频,因为所有现代媒体格式都使用压缩来节省带宽和磁盘空间。
一个典型的H.264格式视频流,在5 Mbps的比特率下,所占空间比具有类似分辨率的未压缩RGB流少100倍。解码算法必须将每一帧恢复到原始分辨率和色彩空间,按照编解码器规范以与编码相反的顺序进行。为此,解码器处理帧内数据(I帧)和帧间数据(P帧、B帧)。
在移动设备上,解码既可以在CPU上执行,也可以在专用的硬件模块上执行。来自Apple(A系列)、Qualcomm(Snapdragon)和MediaTek(Dimensity)的现代SoC都包含了针对所有流行格式的内置解码器。视频处理器承担了逆离散余弦变换和运动补偿的繁重工作,将CPU释放出来处理其他任务。
解码过程由多个连续阶段组成,这些阶段逆着编码的步骤进行。首先,从比特流中提取标头和压缩参数——配置文件、级别、分辨率、色彩空间。然后,解码器顺序处理压缩的宏块,对它们应用逆变换。
第一阶段——提取熵编码。熵解码使用CABAC或CAVLC算法来恢复离散余弦变换的系数。这个阶段不依赖于视频的分辨率——它处理的是比特流,而不是像素,其复杂度由比特率决定,而不是帧的大小。
第二阶段——逆量化和逆DCT。解码器将量化系数乘以量化步长,恢复DCT系数的近似值,然后应用逆DCT变换。逆DCT从频域恢复空间数据,形成一个像素宏块。对于色度和亮度,变换是独立执行的。
第三阶段——运动补偿。对于P帧和B帧,解码器使用从比特流中提取的运动向量,并引用先前解码的参考帧。运动补偿创建当前宏块的预测器,并将逆DCT后的残差信号添加到其中。结果是一个完全恢复的帧,准备好输出。
// 视频帧基本解码的伪代码
struct DecodedFrame {
uint8_t* y_plane;
uint8_t* u_plane;
uint8_t* v_plane;
int width, height;
};
class Decoder {
public:
bool decodeNALUnit(const uint8_t* nalUnit, size_t size) {
if (!parseNALUHeader(nalUnit, size))
return false;
int sliceType = parseSliceType(nalUnit);
entropyDecode(nalUnit);
inverseQuantize();
inverseDCT();
if (sliceType != I_SLICE)
motionCompensation();
return true;
}
};
上面的示例展示了H.264解码器的基本结构。decodeNALUnit函数接收一个NAL单元——压缩H.264流的基本块。解码器顺序解析标头,提取slice类型,应用熵解码、逆量化和逆DCT。对于P和B slice,还使用DPB缓冲区中的参考帧进行运动补偿。
现代视频编解码器在压缩算法、效率和计算资源需求方面各不相同。格式的选择直接影响文件大小、图像质量以及移动设备解码时的能耗。
| 编解码器 | 年份 | 压缩比 | 硬件支持 |
|---|---|---|---|
| H.264 | 2003 | 1:100 | 所有现代SoC |
| H.265 | 2013 | 1:200 | Apple A8+,Snapdragon 805+ |
| VP9 | 2013 | 1:180 | Snapdragon 820+,Exynos |
| AV1 | 2018 | 1:300 | Apple A17+,Snapdragon 8 Gen 2+ |
H.264是最广泛使用的视频编解码器,受到所有移动设备的支持。其主要优势是通用性:任何Android智能手机和iPhone都可以硬件解码H.264。然而,在相同比特率下,H.264在质量上不如更现代的H.265和AV1编解码器,需要多30–50%的比特率才能达到类似的视觉质量。
H.265在相同质量下提供比H.264好两倍的压缩。H.265的解码需要更强大的硬件模块:iOS上的VideoToolbox从iPhone 6(A8)开始支持H.265,Android设备从Snapdragon 805及以上开始支持。在为移动应用选择H.265时,需要考虑较旧的设备可能没有硬件支持,将通过软件解码此格式,这将急剧增加能耗。
AV1是来自开放媒体联盟(Alliance for Open Media)的开放编解码器,在所有现代格式中提供最佳的压缩效果。在相同视觉质量下,AV1比H.265高效30%,比H.264高效50%。AV1硬件解码仅在2023年以后的SoC中出现:Apple A17 Pro、Qualcomm Snapdragon 8 Gen 2及更新产品。对于较旧的设备,AV1解码只能通过dav1d库以软件方式进行,这会给CPU造成显著负载。
在软件解码和硬件解码之间进行选择是开发移动媒体播放器时的关键架构决策。每种方法都有其优点和局限性,在设计应用程序时必须加以考虑。
硬件解码在专门的视频处理模块上执行,在执行相同任务时比CPU消耗的能量少得多。根据Qualcomm的数据,在播放4K视频时,H.265硬件解码器比Snapdragon 8 Gen 1 CPU上的软件解码节能5–10倍。这对于移动设备至关重要,因为每毫瓦都会影响电池续航。
相比之下,软件解码提供了最大的灵活性。FFmpeg及其libavcodec库支持数十种编解码器和容器,包括没有硬件支持的罕见和过时格式。开发人员可以修改解码管道,动态添加后处理和滤镜,这是使用封闭的硬件模块时无法实现的。
软件解码在以下几种情况下是合理的:播放罕见格式(ProRes、DNxHD、Motion JPEG)时,需要对每一帧处理阶段进行精确控制时,以及在无硬件支持的设备上解码AV1时。libavcodec(来自FFmpeg)可以解码几乎所有已知的格式,这使其成为通用媒体播放器的事实标准。
软件解码的局限性是发热。在CPU上持续解码4K视频可能在10–15分钟内将设备加热到45–50度,导致降频和帧率下降。在没有主动冷却的设备(平板电脑、手机)上,这一点尤为明显。软件解码时的CPU功耗可能达到3–5W,而相同流的硬件解码仅为0.3–0.5W。
硬件解码是任何生产级媒体播放器的默认选择。它能为4K视频提供稳定的60帧/秒,且能耗最低。iOS上的VideoToolbox和Android上的MediaCodec为硬件解码提供了原生API,可根据编解码器和分辨率自动选择最佳的处理模块。
平台API负责帧缓冲区的管理(Android上的surface pool,iOS上的CVPixelBufferPool)、与显示器的同步以及内存优化。开发人员只需使用正确的参数打开解码器即可接收就绪的帧。硬件解码支持端到端管道,延迟极低:从接收比特流到显示在屏幕上只需5–15毫秒,而软件解码需要30–80毫秒。
让我们来看看两个移动平台上的实际解码实现。在iOS上,硬件解码通过VideoToolbox执行,软件解码通过FFmpeg执行。在Android上,使用MediaCodec进行硬件解码。
@interface VideoDecoder ()
@property (nonatomic) VTDecompressionSessionRef session;
@end
@implementation VideoDecoder
- (void)setupDecoder {
CMVideoFormatDescriptionRef formatDesc;
CMVideoCodecType codecType = kCMVideoCodecType_H264;
OSStatus status = CMVideoFormatDescriptionCreate(
NULL, codecType, 1920, 1080, NULL, &formatDesc
);
VTDecompressionOutputCallbackRecord callback;
callback.decompressionOutputCallback = &decodingCallback;
VTDecompressionSessionCreate(NULL, formatDesc, NULL,
NULL, &callback, &_session);
}
- (void)decodeFrame: (uint8_t*)nalData length:(size_t)size {
CMBlockBufferRef blockBuffer;
CMBlockBufferCreateWithMemoryBlock(NULL, nalData,
size, NULL, NULL, 0, size, 0, &blockBuffer);
CMSampleBufferRef sampleBuffer;
CMSampleBufferCreate(NULL, blockBuffer, true, NULL,
NULL, NULL, 1, 0, NULL, 0, NULL, &sampleBuffer);
VTDecompressionSessionDecodeFrame(_session,
sampleBuffer, 0, NULL, 0);
}
@end
代码演示了iOS上H.264硬件解码器的初始化。VTDecompressionSessionCreate创建解码会话,VTCreate在就绪帧出现时调用回调。会话会自动使用硬件模块(如果可用于指定的编解码器)。为了接收CVPixelBuffer格式的解码帧,使用了一个回调,以最小延迟传递每个就绪帧。
MediaCodec decoder = MediaCodec.createDecoderByType("video/avc");
MediaFormat format = MediaFormat.createVideoFormat(
"video/avc", 1920, 1080
);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
decoder.configure(format, surface, null, 0);
decoder.start();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
int inputIndex = decoder.dequeueInputBuffer(10000);
if (inputIndex >= 0) {
ByteBuffer buffer = inputBuffers[inputIndex];
buffer.clear();
buffer.put(nalData);
decoder.queueInputBuffer(inputIndex, 0, nalData.length, pts, 0);
}
在Android上,MediaCodec使用Surface而非像素缓冲区进行输出,从而最大限度地减少了GPU和CPU之间的数据复制。解码器根据编解码器类型自动选择硬件模块(OMX组件)。对于H.264,使用OMX.google.h264.decoder,根据制造商的实现,它可以是硬件或软件解码器。
解码策略的选择取决于应用的目标受众、支持的格式和性能要求。最优解决方案通常包括混合方法:对主要格式(H.264、H.265)使用硬件解码,对罕见编解码器使用软件后备。
如果应用面向最大兼容性——使用H.264,它保证在任何设备上都能进行硬件解码。对于视频流服务,在2016年以后的设备上具有硬件支持的H.265是合理的选择。AV1是注重带宽节省的服务的首选:YouTube、Netflix和其他主要平台正在积极采用AV1,以在保持质量的同时降低CDN成本。
关键参数——解码器的缓冲区大小。硬件解码器具有固定的缓冲池(通常为4–16帧)。在播放高比特率流时,缓冲区可能会溢出,导致丢帧。MediaCodec提供了getOutputFrameRate方法来评估特定设备上解码器的实际性能,VideoToolbox允许通过kVTDecodeFrame_EnableAsynchronousDecompression控制实时优先级。
热降频是另一个因素。即使是硬件解码在长时间播放4K HDR视频时也会使设备发热。建议通过iOS上的ProcessInfo和Android上的BatteryManager监控温度,在过热时降低流的质量或分辨率。这对于具有长时间观看会话的游戏和流媒体应用尤其重要。
常见问题
编码(encoding)将未压缩数据转换为压缩格式,而解码(decoding)从压缩流中恢复原始数据。这两个过程互为逆过程,使用相同的算法:DCT、量化、运动补偿。编码器执行正向变换,解码器执行逆向变换。
为了最大兼容性——H.264,因为它在100%的现代设备上都可以硬件解码。为了更好的压缩——H.265或AV1。选择取决于受众:如果80%的用户拥有2021年以后的设备,H.265将能在较低的比特率下提供更好的质量。AV1适用于具有2023年以后硬件支持的旗舰设备。
硬件解码器是为解码而设计的专用微芯片(ASIC)。与通过顺序指令执行解码的CPU不同,硬件模块并行处理宏块。硬件解码器的能耗低5–10倍,因为芯片在较低的频率下工作,并且没有额外的流水线阶段。
配置文件(profile)定义了编码器使用的压缩算法集:Baseline、Main、High。级别(level)设置了流的最大参数:分辨率、比特率、缓冲区大小。对于移动设备,推荐使用High配置文件和4.1–5.2级别——这对于具有硬件解码的1080p–4K视频是足够的。
在Android上,使用MediaCodecList获取可用编解码器列表并检查哪些是硬件解码器。在iOS上,使用CMVideoFormatDescription检查对指定编解码器的支持——如果VTDecompressionSessionCreate成功,则支持该编解码器。对于Android上的AV1,检查OMX.google.aomc.decoder编解码器或其硬件版本是否存在。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。