28、H.264视频压缩标准详解

H.264视频压缩标准详解

1. 视频编码标准发展背景

早期的视频编码标准如MPEG - 1和MPEG - 2在不同应用场景中发挥了重要作用。MPEG - 1目标比特率约为1.5 Mb/s,而MPEG - 2适用于10 Mb/s及以上的比特率,广泛用于电视广播。

随着手机和无线网络技术的成熟,对低比特率且抗误码的视听编码标准的需求日益增长。这促使了MPEG - 4标准的诞生,它采用了更高效的压缩方案。

然而,高清电视(HDTV)的广泛应用,以及卫星广播、电缆调制解调器、DSL或UMTS等不同传输介质的出现,对视频压缩效率提出了更高要求。这些传输介质的数据速率低于广播频道,因此需要更高压缩效率的标准,以在现有低数据速率媒体上提供更多视频频道或更高质量的视频。这就推动了H.264或AVC视频压缩标准的出现。

2. H.264/AVC标准概述

H.264/AVC标准旨在满足多种服务媒体的需求,它涵盖了两个系统:
- 高效视频编码层(VCL) :用于视频数据的压缩。
- 网络抽象层(NAL) :将VCL数据格式化为适合各种服务媒体携带压缩材料的形式。

该标准提供了多种解决方案,包括:
1. 通过卫星、电缆调制解调器、DSL等进行广播。
2. 在蓝光DVD等光学或磁记录设备上进行交互式或串行存储。
3. 在局域网、以太网、无线和移动网络等上提供对话服务。
4. 通过电缆调制解调器、DSL等提供视频点播或多媒体流服务。
5. 通过DSL、ISDN、移动和无线网络等提供多媒体消息服务。

3. H.264/AVC的特性亮点

与MPEG - 2相比,H.264/AVC在提高压缩效率方面有诸多独特特性:
|特性|描述|
| ---- | ---- |
|可变块大小运动补偿|可对小至4×4像素的块进行运动补偿,而非固定大小的宏块。图像中细节丰富的区域噪声可见阈值高,可进行大量量化而不产生可见失真,从而提高压缩率。|
|四分之一像素预测|将运动估计精度提高到四分之一像素,减少预测残差,提高编码效率。|
|跨图像边界的运动向量|使用图像边界外推,允许运动向量指向先前重建参考图像之外的区域。|
|多参考图像运动补偿|允许相对于多个已重建的参考图像进行运动补偿,提高编码效率,也适用于B帧编码。|
|独立的解码和显示顺序|编码器可以高度灵活地选择图像的解码和显示顺序,消除了与B帧相关的额外延迟。|
|B帧编码的灵活性|取消了早期标准中B帧编码只能使用先前编码的I帧或P帧的限制,允许参考更接近当前编码图像的图像。|
|加权预测|对运动补偿预测残差进行加权和偏移,提高编码效率。|
|改进的帧内预测|使用方向预测提高编码效率。|
|环路去块滤波器|在预测环路中使用去块滤波,既改善预测效果,又消除基于DCT编码中因使用矩形像素块而产生的块效应。|
|4×4变换|使用类似4×4 DCT的变换来压缩帧内编码中的预测残差,变换核系数为整数,如下所示:
$H = \begin{bmatrix}1 & 1 & 1 & 1\2 & 1 & -1 & -2\1 & -1 & -1 & 1\1 & -2 & 2 & -1\end{bmatrix}$|
|分层块变换|使用分层变换将低频色度信息的有效块大小扩展到8×8,还使用特殊的帧内编码类型对16×16亮度块进行编码。|
|短字长变换|在块变换计算中仅需要16位算术运算,不同于以往标准通常需要更高的算术精度。|
|逆变换精确匹配|确保所有解码器的解码视频完全相同,避免因逆变换不匹配导致的编码器和解码器之间的漂移。|
|高级算术编码|使用CABAC(上下文自适应二进制算术编码)和CAVLC(上下文自适应可变长度编码)两种高级算术编码方法,提高性能。|

4. H.264宏块编码

和其他MPEG标准一样,H.264中的宏块由一个16×16的亮度块和两个8×8的色度(Cb和Cr)分量块组成。一个片由多个宏块构成,并且H.264采用灵活宏块排序(FMO),片不必按光栅扫描顺序排列。

在使用4×4块进行帧内空间预测时,支持九种预测模式,具体如下:
- 模式0 :垂直预测
- 模式1 :水平预测
- 模式2 :DC预测
- 模式3 :左下对角线预测
- 模式4 :右下对角线预测
- 模式5 :垂直右预测
- 模式6 :水平下预测
- 模式7 :垂直左预测
- 模式8 :水平上预测

4×4块预测主要用于压缩细节丰富的区域,而16×16块则用于帧内编码平坦区域(像素空间变化相对较小的区域)。16×16块的帧内预测使用四种模式:垂直预测、水平预测、DC预测和平面预测。

在P帧的运动补偿预测编码中,会使用4×4、8×8和16×16大小的块,并且有16×16、16×8、8×16和8×8等可能的组合。如果使用8×8块预测,H.264还支持8×4、4×8和4×4块。

5. H.264帧内4×4预测示例

以摄像师图片为例,展示如何进行4×4块的帧内预测。具体步骤如下:
1. 图像预处理 :由于不使用片组,给图片顶部添加一行、左侧添加一列、右侧添加四列进行填充。
2. 预测过程 :从左上角开始,按光栅扫描顺序对4×4块进行预测,得到预测残差。
3. 计算预测增益 :计算输入图片方差与预测残差方差的比值(以dB表示)。

以下是不同图片的4×4方向帧内预测的预测增益:
|输入图片|预测增益(dB)|
| ---- | ---- |
|Aerial|7.27|
|Airplane|18.84|
|Birds|16.26|
|Cameraman|11.80|
|Lighthouse|9.62|
|Masuda1|22.68|
|Peppers|18.14|
|Yacht|13.92|

可以看出,图片的预测增益因图像内容而异。例如,Aerial图片细节最多,其预测增益最低。

6. MATLAB代码实现4×4方向帧内预测
% Example10 5.m
% Program to do 4 x 4 directional intra prediction
% using the 9 modes specified in H.264.
% The 9 modes are as follows:
% Mode 0: Vertical prediction
% Mode 1: Horizontal prediction
% Mode 2: DC prediction
% Mode 3: Diagonal down-left prediction
% Mode 4: Diagonal down-right prediction
% Mode 5: Vertical-right prediction
% Mode 6: Horizontal-down prediction
% Mode 7: Vertical-left prediction
% Mode 8: Horizontal-up prediction
% Only luma prediction is incorporated.
% No FMO is used and the macro blocks are scanned in
% raster scan order.
clear
A1 = imread('cameraman.tif');
% Make image size divisible by 4
[X,Y,Z] = size(A1);
if mod(X,4)~=0
    Height = floor(X/4)*4;
else
    Height = X;
end
if mod(Y,4)~=0
    Width = floor(Y/4)*4;
else
    Width = Y;
end
Depth = Z;
clear X Y Z
% if the input image is RGB, then convert it to YCbCr & retain only the
% Y component.
if Depth == 3
    A1 = rgb2ycbcr(A1(1:Height,1:Width,:));
    A = double(A1(:,:,1));
else
    A = double(A1(1:Height,1:Width));
end
% Input Y padded by 1 row on the top and
% 1 column to the left and 4 columns to the right.
B = zeros(Height+1,Width+5);
E = zeros(Height,Width); % Intra prediction error image
% Fill in the B array
B(2:Height+1,2:Width+1) = A;
B(1,2:Width+1) = A(1,:);
B(2:Height+1,1) = A(:,1);
B(1,1) = A(1,1);
for k = 2:5
    B(2:Height+1,Width+k) = A(:,256);
end
for k = 2:5
    B(1,Width+k) = B(2,Width+k);
end
% Do intra 4 x 4 prediction using 9 orientations.
% by calling the function "IntraBlkPredict".
% The returned values are: "PredictedBlk" is the predicted 4 x 4
% block corresponding to the current 4 x 4 block, and
% "Dist" is the SAD value corresponding to the best matching block.
for m = 2:4:Height+1
    for n = 2:4:Width+1
        CurrentBlk = B(m:m+3,n:n+3);
        [PredictedBlk,Dist] = IntraBlkPredict(B,m,n,CurrentBlk);
        E(m-1:m+2,n-1:n+2) = CurrentBlk - PredictedBlk;
    end
end
%
figure,imshow(E,[]), title('Intra prediction error')
%
sprintf('Prediction Gain = %5.2f dB\n',20*log10(std2(A)/std2(E)))
% Compute the prediction error histogram
[H,Bin] = hist(E,100);
figure,plot(Bin,H/sum(H),'k'), title('Intra prediction error histogram')
xlabel('Pixel error')
ylabel('Relative frequency')

function [MatchingBlk,SAD] = IntraBlkPredict(A,Current row,
Current col,CurrentBlk)
% [MatchingBlk,SAD] = IntraBlkPredict(A,Row,Col,CurrentBlk)
% Function to perform 4 x 4 intra block prediction
% using the 9 directional prediction schemes used in H.264
% Input:
%     A is the padded input image
%     (Current row, Current col) is the coordinate of the top left
%     corner of the current block
%     CurrentBlk is the current block being predicted.
% Output:
%     MatchingBlk is the predicted block
%     SAD is the sum of absolute error (city block distance)
%
% The 9 directional prediction modes are numbered 0 through 8.
% The block that results in the least value of SAD is the
% predicted block.
%
SAD = 99999;
MatchingBlk = zeros(8,8);
for k = 0:8
    switch k
        case 0
            % Vertical Mode
            for n = 1:4
                CurrentBlk(:,n) = A(Current row-1,Current col+n-1);
            end
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
        case 1
            % Horizontal Mode
            for m = 1:4
                CurrentBlk(m,:) = A(Current row + m -1,
                Current col - 1);
            end
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
        case 2
            % DC (Average) Mode
            Val = sum(A(Current row-1,Current col:Current col+7))...
            + sum(A(Current row:Current row+3,Current col-1))...
            + A(Current row-1,(Current col-1));
            CurrentBlk(:,:) = round(Val/13);
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
        case 3
            % Diagonal down left Mode
            for m = 1:4
                n = m + 3;
                CurrentBlk(m,1:4) = A(Current row -
                1,Current col+m:Current col+n);
            end
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
        case 4
            % Diagonal down right Mode
            for m = 1:4
                CurrentBlk(m,m) = A(Current row -1,Current col-1);
            end
            for m = 2:4
                CurrentBlk(m,m-1) = A(Current row,Current col-1);
            end
            for m = 3:4
                CurrentBlk(m,m-2) = A(Current row+1,Current col-1);
            end
            CurrentBlk(4,1) = A(Current row+2,Current col-1);
            for n = 2:4
                CurrentBlk(n-1,n) = A(Current row-1,Current col);
            end
            for n = 3:4
                CurrentBlk(n-2,n) = A(Current row-1,Current col+1);
            end
            CurrentBlk(1,4) = A(Current row-1,Current col+2);
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
        case 5
            % Vertical right Mode
            for m = 1:4
                CurrentBlk(m,m) = A(Current row-1,Current col);
            end
            for m = 1:3
                CurrentBlk(m,m+1) = A(Current row-1,Current col+1);
            end
            for m = 1:2
                CurrentBlk(m,m+2) = A(Current row-1,Current col+2);
            end
            CurrentBlk(1,4) = A(Current row-1,Current col+3);
            for m = 2:4
                CurrentBlk(m,m-1) = A(Current row-1,Current col-1);
            end
            for m = 3:4
                CurrentBlk(m,m-2) = A(Current row,Current col-1);
            end
            CurrentBlk(4,1) = A(Current row+1,Current col-1);
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
        case 6
            % horizontal down Mode
            for m = 1:4
                CurrentBlk(m,m) = A(Current row,Current col-1);
            end
            for m = 2:4
                CurrentBlk(m,m-1) = A(Current row+1,Current col-1);
            end
            for m = 3:4
                CurrentBlk(m,m-2) = A(Current row+2,Current col-1);
            end
            CurrentBlk(4,1) = A(Current row+3,Current col-1);
            for m = 1:3
                CurrentBlk(m,m+1) = A(Current row-1,Current col-1);
            end
            for m = 1:2
                CurrentBlk(m,m+2) = A(Current row-1,Current col);
            end
            CurrentBlk(1,4) = A(Current row-1,Current col+1);
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
        case 7
            % Vertical left Mode
            CurrentBlk(1,1) = A(Current row-1,Current col);
            CurrentBlk(1,2) = A(Current row-1,Current col+1);
            CurrentBlk(2,1) = A(Current row-1,Current col+1);
            CurrentBlk(3,1) = A(Current row-1,Current col+1);
            CurrentBlk(1,3) = A(Current row-1,Current col+2);
            CurrentBlk(2,2) = A(Current row-1,Current col+2);
            CurrentBlk(3,2) = A(Current row-1,Current col+2);
            CurrentBlk(4,1) = A(Current row-1,Current col+2);
            CurrentBlk(1,4) = A(Current row-1,Current col+3);
            CurrentBlk(2,3) = A(Current row-1,Current col+3);
            CurrentBlk(3,3) = A(Current row-1,Current col+3);
            CurrentBlk(4,2) = A(Current row-1,Current col+3);
            CurrentBlk(2,4) = A(Current row-1,Current col+4);
            CurrentBlk(3,4) = A(Current row-1,Current col+4);
            CurrentBlk(4,3) = A(Current row-1,Current col+4);
            CurrentBlk(4,4) = A(Current row-1,Current col+5);
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
        case 8
            % horizontal up Mode
            CurrentBlk(1,1) = A(Current row,Current col-1);
            CurrentBlk(2,1) = A(Current row+1,Current col-1);
            CurrentBlk(1,2) = A(Current row+1,Current col-1);
            CurrentBlk(1,3) = A(Current row+1,Current col-1);
            CurrentBlk(3,1) = A(Current row+2,Current col-1);
            CurrentBlk(2,2) = A(Current row+2,Current col-1);
            CurrentBlk(2,3) = A(Current row+2,Current col-1);
            CurrentBlk(1,4) = A(Current row+2,Current col-1);
            CurrentBlk(4,1) = A(Current row+3,Current col-1);
            CurrentBlk(3,2) = A(Current row+3,Current col-1);
            CurrentBlk(3,3) = A(Current row+3,Current col-1);
            CurrentBlk(2,4) = A(Current row+3,Current col-1);
            CurrentBlk(4,2) = A(Current row+3,Current col-1);
            CurrentBlk(4,3) = A(Current row+3,Current col-1);
            CurrentBlk(3,4) = A(Current row+3,Current col-1);
            CurrentBlk(4,4) = A(Current row+3,Current col-1);
            d = sum(sum(abs(CurrentBlk-A(Current row:Current row+3,
            Current col:Current col+3))));
            if d < SAD
                SAD = d;
                MatchingBlk = CurrentBlk;
            end
    end
end
7. 总结

视频编码标准的发展是为了适应不同应用场景的需求。H.264/AVC标准在压缩效率上比MPEG - 2有显著提升,能够在更低的带宽下提供相同质量的视频,或者在相同带宽下提供更高质量的视频。

其独特的特性,如可变块大小运动补偿、四分之一像素预测、多参考图像运动补偿等,使得它在各种服务媒体中都能表现出色。通过对H.264宏块编码和帧内预测的详细介绍,我们可以更好地理解其工作原理。同时,通过具体的示例和MATLAB代码,我们可以更直观地看到H.264在实际应用中的效果。

虽然本文没有详细介绍MPEG - 4的误码恢复特性,但在移动或无线网络中,误码恢复是一个重要的问题。MPEG - 4的误码恢复特性可以使视频解码器更具抗误码能力,提供更可接受的视频质量。

H.264视频压缩标准详解

8. H.264与其他标准对比优势分析

H.264相较于MPEG - 1、MPEG - 2和MPEG - 4等标准,具有多方面的显著优势,以下通过表格进行详细对比:
|标准|比特率适用范围|应用场景|压缩效率|独特特性|
| ---- | ---- | ---- | ---- | ---- |
|MPEG - 1|约1.5 Mb/s|主要用于早期的视频存储和传输,如VCD|较低|固定宏块大小,简单的运动补偿|
|MPEG - 2|10 Mb/s或更高|广泛用于电视广播,包括SDTV和HDTV|一般|支持隔行扫描,适用于高分辨率视频|
|MPEG - 4|低比特率|适用于移动和无线网络视频,交互式节目|较高|引入基于对象的编码|
|H.264|灵活,可适应不同数据速率|多种服务媒体,如卫星广播、视频点播等|高|可变块大小运动补偿、四分之一像素预测、多参考图像运动补偿等|

从表格中可以看出,H.264在压缩效率上具有明显优势,能够在不同的比特率下提供高质量的视频。其独特的特性使得它能够更好地适应各种复杂的应用场景,尤其是在低带宽和高分辨率的情况下表现出色。

9. H.264在实际应用中的流程分析

为了更清晰地理解H.264在实际应用中的工作流程,下面通过mermaid流程图进行展示:

graph TD;
    A[输入视频] --> B[帧内预测];
    B --> C[运动估计与补偿];
    C --> D[变换与量化];
    D --> E[熵编码];
    E --> F[输出压缩视频];
    G[参考帧] --> C;
    C --> H[环路去块滤波];
    H --> G;
  • 输入视频 :原始的视频数据作为整个编码流程的起点。
  • 帧内预测 :对当前帧进行预测,减少空间冗余。H.264支持多种帧内预测模式,如4×4块的九种模式和16×16块的四种模式。
  • 运动估计与补偿 :通过比较当前帧与参考帧之间的差异,找到最佳的运动向量,从而减少时间冗余。H.264支持可变块大小和多参考图像运动补偿。
  • 变换与量化 :对预测残差进行变换,将其转换到频域,然后进行量化,减少数据量。H.264使用4×4变换和分层块变换。
  • 熵编码 :对量化后的系数进行编码,进一步压缩数据。H.264使用CABAC和CAVLC两种高级算术编码方法。
  • 输出压缩视频 :经过上述步骤处理后,得到压缩后的视频数据。
  • 环路去块滤波 :在预测环路中进行去块滤波,消除块效应,提高视频质量。滤波后的帧作为参考帧用于后续的编码。
10. H.264未来发展趋势展望

随着视频技术的不断发展,H.264虽然已经取得了巨大的成功,但仍然面临着一些挑战和机遇,以下是对其未来发展趋势的展望:
- 更高的压缩效率 :随着高清、超高清视频的普及,对压缩效率的要求越来越高。未来H.264可能会进一步优化其算法,提高压缩比,以适应更高分辨率和更低带宽的需求。
- 更好的兼容性 :随着各种设备和平台的不断涌现,H.264需要更好地兼容不同的硬件和软件环境。未来可能会出现更多的优化方案,以确保在各种设备上都能实现高效的解码和播放。
- 与新兴技术的融合 :随着人工智能、机器学习等新兴技术的发展,H.264可能会与这些技术进行融合,实现更智能的视频编码和解码。例如,利用机器学习算法进行运动估计和预测,提高编码效率和视频质量。
- 增强的抗误码能力 :在无线网络和移动设备中,误码是一个常见的问题。未来H.264可能会进一步增强其抗误码能力,提高视频在不稳定网络环境下的传输质量。

11. 对H.264学习和实践的建议

对于想要深入学习和实践H.264的读者,以下是一些建议:
- 理论学习 :系统学习视频编码的基础知识,包括运动补偿、变换编码、熵编码等。了解H.264的标准文档和相关技术原理,掌握其核心算法和特性。
- 代码实践 :通过编写代码实现H.264的部分功能,如帧内预测、运动估计等。可以参考开源的H.264编码器和解码器,如x264和FFmpeg,学习其实现细节。
- 实验测试 :使用不同的视频序列进行实验测试,比较H.264与其他标准的压缩效果和视频质量。通过调整编码参数,如比特率、帧率等,观察其对视频质量和压缩效率的影响。
- 参与社区 :加入相关的技术社区和论坛,与其他开发者交流经验和心得。关注行业动态和最新研究成果,不断更新自己的知识。

12. 总结

H.264作为一种先进的视频压缩标准,在视频领域发挥着重要的作用。它在压缩效率、灵活性和适应性等方面都具有显著优势,能够满足不同应用场景的需求。

通过本文的详细介绍,我们对H.264的发展背景、标准概述、特性亮点、宏块编码、实际应用流程以及未来发展趋势等方面有了更深入的了解。同时,通过具体的示例和代码实现,我们可以更直观地感受到H.264的强大功能。

在未来的视频技术发展中,H.264将继续发挥重要作用,并且可能会不断优化和改进,以适应不断变化的市场需求。希望本文能够为读者提供有价值的参考,帮助大家更好地掌握和应用H.264视频压缩标准。

分布式微服务企业级系统是一个基于Spring、SpringMVC、MyBatis和Dubbo等技术的分布式敏捷开发系统架构。该系统采用微服务架构和模块化设计,提供整套公共微服务模块,包括集中权限管理(支持单点登录)、内容管理、支付中心、用户管理(支持第三方登录)、微信平台、存储系统、配置中心、日志分析、任务和通知等功能。系统支持服务治理、监控和追踪,确保高可用性和可扩展性,适用于中小型企业的J2EE企业级开发解决方案。 该系统使用Java作为主要编程语言,结合Spring框架实现依赖注入和事务管理,SpringMVC处理Web请求,MyBatis进行数据持久化操作,Dubbo实现分布式服务调用。架构模式包括微服务架构、分布式系统架构和模块化架构,设计模式应用了单例模式、工厂模式和观察者模式,以提高代码复用性和系统稳定性。 应用场景广泛,可用于企业信息化管理、电子商务平台、社交应用开发等领域,帮助开发者快速构建高效、安全的分布式系统。本资源包含完整的源码和详细论文,适合计算机科学或软件工程专业的毕业设计参考,提供实践案例和技术文档,助力学生和开发者深入理解微服务架构和分布式系统实现。 【版权说明】源码来源于网络,遵循原项目开源协议。付费内容为本人原创论文,包含技术分析和实现思路。仅供学习交流使用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值