【x264】x264编码库的安装与使用

1.x264编码库简介

X264是一个开源的H.264/MPEG-4 AVC视频编码器库。它是一个纯软件的H.264视频编码器,完全基于CPU进行运算,不依赖硬件编码器驱动

官网:x264, the best H.264/AVC encoder - VideoLAN

代码仓库:VideoLAN / x264 · GitLab

1.1 x264编码库的特点

x264不依赖任何硬件编码器,而是通过高度优化的C语言和汇编代码实现所有的编码算法,有以下特点:

1.纯CPU运算

  • 所有编码步骤,变换,量化,运动估计,熵编码等,都是CPU做的
  • 通过多线程并行化利用多核CPU性能

2.多层优化

  • 基于C语言实现:易于移植
  • 平台专属汇编优化:针对x86/ARM等架构的SIMD指令集优化关键函数
  • 算法优化:快速运动估计算法、自适应量化等

3.模块化设计

graph LR
A[原始YUV帧] --> B[帧内预测]
A --> C[帧间预测]
B & C --> D[变换量化]
D --> E[熵编码]
E --> F[H.264比特流]

image

1.2 x264的核心编码流程

1.预测编码:

  • 帧间预测:利用当前帧内相邻块预测(9种4x4模式,4种16x16模式)
  • 帧间预测:运动估计和运动补偿

2.变换与量化

  • 对残差数据进行整数DCT变换(4x4/8x8)
  • 通过量化矩阵控制约压缩强度

3.熵编码

  • CAVLC (上下文自适应变长编码):默认用于 Baseline/Extended Profile
  • CABAC (上下文自适应二进制算术编码):用于 Main/High Profile(压缩率更高)

4.码率控制

  • 支持CQP/CRF/ABR等多种模式
  • 通过MB-tree、psy-RD等算法优化视觉质量

2.x264编码库安装

2.1 通过APT安装(版本未必最新)

sudo apt update
sudo apt install x264 libx264-dev

  • x264:提供命令行工具x264(没有头文件和动态库)
  • libx264-dev:开发库,用于C/C++程序中使用x264编码

验证安装:

x264 --version
# x264 --version
x264 0.152.2854 e9a5903
(libswscale 4.8.100)
(libavformat 57.83.100)
(ffmpegsource 2.23.0.0)
built on Jan 19 2018, gcc: 7.2.0
x264 configuration: --bit-depth=8 --chroma-format=all
libx264 configuration: --bit-depth=8 --chroma-format=all
x264 license: GPL version 2 or later
libswscale/libavformat/ffmpegsource license: GPL version 2 or later

以上表示安装成功

2.2 从源码编译安装(可以任选版本)

git clone https://code.videolan.org/videolan/x264.git
cd x264

配置并编译

./configure --enable-shared --enable-static
make -j 4  # 使用多核编译加快速度
sudo make install

--enable-shared:生成动态链接库.so文件

--enable-static:生成静态链接库.a文件

验证安装

x264 --version

3.x264的关键参数

3.1 基本参数

参数名 说明 典型值
i_width 视频宽度 640/1280/1920
i_height 视频高度 480/720/1080
i_fps_num 帧率分子 30
i_fps_den 帧率分母 1
i_csp 色彩空间 X264_CSP_I420

3.2 编码质量参数

参数名 说明 典型值
i_bitdepth 位深 8/10
rc.i_bitrate 目标码率(kbps) 1000-8000
rc.i_rc_method 码率控制方法 X264_RC_ABR/CRF/CQP
rc.f_rf_constant CRF质量系数 18-28
i_keyint_max 最大关键帧间隔 250

3.3 性能参数

参数名 说明 典型值
i_threads 编码线程数 CPU核心数
b_sliced_threads 切片线程 1
i_lookahead_threads 前瞻线程 0-8

4.x264编码库核心API

4.1 初始化接口

// 参数初始化
void x264_param_default(x264_param_t *);

// 应用预设配置
int x264_param_default_preset(x264_param_t *, const char *preset, const char *tune);

// 打开编码器
x264_t* x264_encoder_open(x264_param_t *);

// 分配图像内存
int x264_picture_alloc(x264_picture_t *pic, int i_csp, int i_width, int i_height);

4.2 编码接口

// 编码一帧
int x264_encoder_encode(x264_t *h, 
                       x264_nal_t **pp_nal, 
                       int *pi_nal,
                       x264_picture_t *pic_in,
                       x264_picture_t *pic_out);

// 刷新编码器
int x264_encoder_delayed_frames(x264_t *h);

// 关闭编码器
void x264_encoder_close(x264_t *h);

4.3 参数调整接口

// 动态调整参数
int x264_encoder_reconfig(x264_t *h, x264_param_t *param);

// 获取编码器参数
int x264_encoder_parameters(x264_t *h, x264_param_t *param);

5.x264使用示例

#include <stdio.h>
#include <stdint.h>
#include <x264.h>
#include <stdlib.h>
#include <string.h>

#define WIDTH 640
#define HEIGHT 480
#define FPS 30
#define BITRATE 1000
#define OUTPUT_FILE "test.h264"

int main() {
    x264_t *encoder = NULL;
    x264_picture_t pic_in, pic_out;
    x264_param_t param;
    FILE *fp = fopen(OUTPUT_FILE, "wb");
  
    // 1. 初始化参数
    x264_param_default(&param);
    x264_param_default_preset(&param, "fast", "zerolatency");
  
    param.i_width = WIDTH;
    param.i_height = HEIGHT;
    param.i_fps_num = FPS;
    param.i_fps_den = 1;
    param.i_csp = X264_CSP_I420;
  
    // 码率控制设置
    param.rc.i_rc_method = X264_RC_ABR;
    param.rc.i_bitrate = BITRATE;
    param.rc.i_vbv_max_bitrate = BITRATE * 1.2;
  
    // 关键帧间隔
    param.i_keyint_max = FPS * 2;
    param.b_intra_refresh = 1;
  
    // 2. 打开编码器
    encoder = x264_encoder_open(&param);
    x264_picture_alloc(&pic_in, X264_CSP_I420, WIDTH, HEIGHT);
  
    // 3. 模拟生成测试帧并编码
    for(int i = 0; i < 100; i++) {
        // 生成测试图像(YUV420)
        memset(pic_in.img.plane[0], i%256, WIDTH*HEIGHT);       // Y
        memset(pic_in.img.plane[1], 128, WIDTH*HEIGHT/4);      // U
        memset(pic_in.img.plane[2], 128, WIDTH*HEIGHT/4);      // V
      
        pic_in.i_pts = i;
      
        // 编码帧
        x264_nal_t *nals;
        int i_nal;
        int frame_size = x264_encoder_encode(encoder, &nals, &i_nal, &pic_in, &pic_out);
      
        if(frame_size > 0) {
            for(int j = 0; j < i_nal; j++) {
                fwrite(nals[j].p_payload, 1, nals[j].i_payload, fp);
            }
        }
    }
  
    // 4. 刷新编码器
    while(x264_encoder_delayed_frames(encoder)) {
        x264_nal_t *nals;
        int i_nal;
        int frame_size = x264_encoder_encode(encoder, &nals, &i_nal, NULL, &pic_out);
        if(frame_size > 0) {
            for(int j = 0; j < i_nal; j++) {
                fwrite(nals[j].p_payload, 1, nals[j].i_payload, fp);
            }
        }
    }
  
    // 5. 清理资源
    x264_picture_clean(&pic_in);
    x264_encoder_close(encoder);
    fclose(fp);
  
    printf("Encoding completed. Output saved to %s\n", OUTPUT_FILE);
    return 0;
}

posted @ 2025-06-13 16:49  Emma1111  阅读(856)  评论(0)    收藏  举报