要理解压缩比与码率的相互关系,需从“原始数据量→压缩后数据量”的转换逻辑入手,结合编码器(如x264/x265)的码率控制源码,分析两者的量化关联机制。

一、核心概念与数学关系

1. 定义
  • 原始码率(R_raw):未压缩的视频数据率,公式为:
    R_raw (Mbps) = 宽 × 高 × 帧率 × 位深 × 采样系数 ÷ 1e6
    (采样系数:YUV420为1.5,YUV444为3)
  • 压缩后码率(R_comp):编码输出的码率(单位:Mbps),即我们常说的“码率”。
  • 压缩比(CR)CR = R_raw / R_comp(压缩比越高,压缩效率越好)。
2. 相互决定关系
  • 本质:压缩比是“结果”,码率是“控制目标”,两者通过量化参数(QP) 关联:
    • 编码器通过调整QP控制压缩强度(QP越大,压缩越强),直接决定压缩比;
    • 压缩比反过来约束码率:相同原始数据下,CR越高 → R_comp越低(R_comp = R_raw / CR)。

二、编码器源码中的关联逻辑(以x264为例)

x264(H.264编码器)的码率控制模块(ratecontrol.c)是理解两者关系的核心,其核心逻辑是:通过目标码率计算所需的QP,再通过QP控制压缩比,最终使实际码率逼近目标

1. 原始码率的隐含计算

编码器虽不直接计算原始码率,但通过输入视频参数(宽、高、帧率)间接感知数据量。例如,x264初始化时会记录这些参数:

// x264.c 中初始化视频参数
x264_param_t param;
param.i_width = width;    // 宽度
param.i_height = height;  // 高度
param.i_fps_num = fps_num; // 帧率分子(如30)
param.i_fps_den = fps_den; // 帧率分母(如1)

原始码率可通过这些参数推导(如1080P@30fps→R_raw≈746Mbps),编码器据此判断“需要压缩多少倍”才能达到目标码率(如目标4Mbps→需压缩约186倍)。

2. 码率控制核心:通过QP调整压缩比

x264的码率控制(如CBR模式)通过“目标码率→目标bits per frame→QP调整”的链路,动态控制压缩比。关键函数:x264_ratecontrol_new_frame

(1)计算每帧目标bits

目标码率(param.rc.i_bitrate,单位kbps)转换为每帧目标bits:

// ratecontrol.c 中计算每帧目标bits
int i_bits_per_frame = (int)(param.rc.i_bitrate * 1000.0 / (fps_num / fps_den) + 0.5);
// 例:目标码率4Mbps(4000kbps),30fps → 每帧目标bits = 4000*1000 / 30 ≈ 133333 bits/frame
(2)根据目标bits计算QP

编码器通过“当前帧复杂度→预测所需bits→与目标bits对比→调整QP”的逻辑,控制压缩比:

// 简化逻辑:x264_ratecontrol_new_frame 核心
void x264_ratecontrol_new_frame( x264_t *h )
{
    // 1. 估算当前帧的“复杂度”(基于前帧统计,如纹理复杂度、运动剧烈程度)
    float complexity = estimate_frame_complexity(h);

    // 2. 根据复杂度预测“不调整QP时,该帧会产生的bits”
    float predicted_bits = predict_bits_based_on_complexity(h, complexity, h->rc.last_qp);

    // 3. 对比预测bits与目标bits,计算QP调整量
    if( predicted_bits > h->rc.i_target_bits ) {
        // 预测bits超过目标→需要更强压缩(提高QP)
        h->rc.curr_qp = h->rc.last_qp + 1;
    } else {
        // 预测bits低于目标→可降低压缩(降低QP)
        h->rc.curr_qp = h->rc.last_qp - 1;
    }

    // 4. 限制QP范围(0-51)
    h->rc.curr_qp = clamp( h->rc.curr_qp, 0, 51 );
}
  • 关键逻辑:QP与压缩比正相关(QP↑→压缩比↑→每帧bits↓)。通过调整QP,使实际每帧bits逼近目标,最终整体码率接近设定值。
(3)QP对压缩比的量化影响

x264中,QP与码率的关系通过“R-Q模型”量化(经验公式):
bits ≈ α × (QP + β)^γ(α、β、γ为模型参数,与帧类型/复杂度相关)
实际源码中通过查表(x264_qp2qscale)将QP转换为量化步长(QScale),QScale越大,残差压缩越强,压缩比越高:

// 量化步长与QP的对应表(简化)
static const int qp2qscale[52] = {
    4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,
    24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,
    42,43,44,45,46,47,48,49,50,51,52,53,54,55
};
// QP=20 → QScale=20;QP=26 → QScale=30(步长增大,压缩更强)
3. 压缩比的动态反馈

编码器通过“实际码率→目标码率”的偏差,动态修正压缩比。例如,CBR模式下的“缓冲控制”:

// 缓冲控制:当实际码率超过目标,增加QP提高压缩比
void x264_ratecontrol_buffer_update( x264_t *h, int i_bits )
{
    h->rc.i_buffer += i_bits - h->rc.i_target_bits; // 计算缓冲偏差
    if( h->rc.i_buffer > h->rc.i_buffer_size ) {
        // 缓冲溢出(实际码率过高)→ 强制提高QP(+2),增强压缩
        h->rc.curr_qp = clamp( h->rc.curr_qp + 2, 0, 51 );
    } else if( h->rc.i_buffer < -h->rc.i_buffer_size ) {
        // 缓冲不足(实际码率过低)→ 降低QP(-2),减弱压缩
        h->rc.curr_qp = clamp( h->rc.curr_qp - 2, 0, 51 );
    }
}

三、压缩比与码率的联动实例

以1080P@30fps视频(R_raw≈746Mbps)为例,目标码率4Mbps(R_comp=4Mbps):

  1. 初始压缩比目标:CR = 746 / 4 ≈ 186
  2. 编码器通过x264_ratecontrol_new_frame计算每帧目标bits≈133333 bits。
  3. 若首帧为I帧(复杂度高),预测bits=200000(超过目标),编码器提高QP(如从26→28),增强压缩,使实际bits降至133333,压缩比达到186。
  4. 若后续P帧(复杂度低)预测bits=80000(低于目标),编码器降低QP(如28→26),减弱压缩,bits升至133333,维持压缩比。

四、源码层面的核心结论

  1. 码率是控制目标:编码器通过目标码率计算每帧允许的bits,反向推导所需压缩比(CR = R_raw / R_comp)。
  2. QP是调节旋钮:源码中通过QP控制压缩强度(QP↑→压缩比↑→bits↓),使实际码率逼近目标。
  3. 动态反馈闭环:通过缓冲偏差、帧复杂度等实时调整QP,平衡压缩比与码率的稳定性。

面试题延伸

  1. 为什么QP每增加6,码率约减半?
    答:x264/x265中,QP与量化步长(QScale)近似线性相关(QP每+6,QScale≈×2),而残差信号经量化后的数据量与QScale²成反比(近似),因此码率≈÷2,压缩比≈×2。

  2. 同一视频,H.265的压缩比比H.264高,码率如何变化?
    答:在相同画质下,H.265压缩比更高(CR_H265 > CR_H264),因此码率更低(R_comp = R_raw / CR),通常可节省50%码率。

  3. CBR模式下,复杂场景为什么可能画质下降?
    答:复杂场景(如快速运动)原始数据冗余少,需要更高bits才能保持画质。但CBR强制限制码率(固定R_comp),编码器只能通过提高QP(增强压缩比)来满足码率约束,导致画质下降。

通过源码可见,压缩比与码率的关系是“目标码率驱动压缩比,压缩比通过QP实现,最终反馈调节码率稳定”的闭环系统,核心是QP对压缩强度的精确控制。

Logo

惟楚有才,于斯为盛。欢迎来到长沙!!! 茶颜悦色、臭豆腐、CSDN和你一个都不能少~

更多推荐