X264-libx264编码库

X264编码库libx264实现真正的视频编解码,该编解码算法是基于块的混合编码技术,即帧内/帧间预测,然后对预测值变换、量化,最后熵编码所得。

编码帧的类型分为I帧(x264_type_i)、P帧(x264_type_p)、B帧(x264_type_b),在H264中叫做图像片Slice。

X264把整帧图像看作一个Slice,片中有slice_type_i、slice_type_p、slice_type_b之分。

I帧只有slice_type_i,P帧有slice_type_i、slice_type_p,B帧三种片都有。

X264的H264视频编码过程可以分为三个步骤:首先根据规则判定当前帧的编码类型,如果是B帧,要缓冲存放、获取;然后对待编码图像进行帧内预测、帧间预测、整数DCT变换、量化和熵编码;最后把压缩的H264数据进行NAL层打包输出。

 

X264编码器有关的重要结构体:

x264_image_t:实际参与编码的编码帧图像信息。

1
2
3
4
5
6
7
typedef struct
{
    int i_csp;          //图像空间颜色
    int i_plane;        //图像平面数目
    int i_stride[4];    //每个图像平面的跨度,也就是每一行数据的字节数
    uint8_t *plane[4];  //每个图像平面存放数据的起始地址,plane[0]是Y平面,plane[1]是U平面,plane[2]是V平面
}x264_image_t;          //待编码的图像

x264_picture_t:x264编码器定义便于控制的图像帧,描述一帧的特征。包含x264_image_t和x264_param_t结构体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct
{
    int   i_type;            //帧的类型,初始化为auto,在编码过程自行控制
    int   i_qpplus1;         //此参数减1代表当前帧的量化参数值
    int   i_pic_struct;      //帧的结构类型
    int   b_keyframe;        //输出是否是关键帧
    int64_t   i_pts;         //一帧的显示时间戳
    int64_t   i_dts;         //输出解码时间戳
 
    x264_param_t    *param;         
    x264_image_t     img;          
    x264_image_properties_t    prop;
    x264_hrd_t    hrd_timing;     
    void    *opaque;              
} x264_picture_t;            //x264编码视频帧

x264_param_t:初始化编码器。

1
2
3
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
typedef struct
{
    unsigned int cpu;       //CPU 标志位
    int  i_threads;         //并行编码多帧
    int  b_sliced_threads;  //如果设置为false,一个slice只编码成一个NALU,默认值是true
    int  b_deterministic;   //是否允许非确定性时线程优化
    int  b_cpu_independent; //强制采用典型行为,而不是采用独立于CPU的优化算法
    int  i_sync_lookahead;  //线程超前缓存帧数
    int  i_width;           //视频图像的宽
    int  i_height;          //视频图像的高
    int  i_csp;             //色彩空间设置,仅支持I420
    int  i_level_idc;       //编码复杂度
    int  i_frame_total;     //编码帧的总数, 不知道默认为0即可
 
    struct
    {
        int  i_sar_height;    //样本宽高比的高度
        int  i_sar_width;     //样本宽高比的宽度
        int  i_vidformat;     //视频在编码/数字化之前是什么类型,默认"undef(不设置)"
        int  b_fullrange;     //样本亮度和色度的计算方式,默认"off"
        int  i_colorprim;     //原始色度格式,默认"undef"
        int  i_transfer;      //转换方式,默认"undef"
        int  i_colmatrix;     //设置从RGB计算得到亮度和色度所用的矩阵系数,默认"undef"
        int  i_chroma_loc;    //设置色度采样位置,范围0~5,默认0
    } vui;                    //vui参数集 : 视频可用性信息、视频标准化选项
 
 
    //比特流参数
    int  i_frame_reference;          //最大参考帧数目
    int  i_dpb_size;                 //Decoded picture buffer size
    int  i_keyint_max;               //设定IDR帧之间的最间隔,在此间隔设置IDR关键帧
    int  i_keyint_min;               //设定IDR帧之间的最小间隔, 场景切换小于此值编码位I帧, 而不是 IDR帧
    int  i_scenecut_threshold;       //场景切换阈值,插入I帧
    int  b_intra_refresh;            //是否使用周期帧内刷新替代IDR帧
    int  i_bframe;                   //两个参考帧之间的B帧数目
    int  i_bframe_adaptive;          //自适应B帧判定, 可选取值:X264_B_ADAPT_FAST等
    int  i_bframe_bias;              //控制B帧替代P帧的概率,范围-100 ~ +100,该值越高越容易插入B帧,默认0
    int  i_bframe_pyramid;           //允许部分B帧为参考帧,可选取值:0=off,  1=strict hierarchical,  2=normal
    int  b_open_gop;                 //帧间的预测都是在GOP中进行,后一个GOP会参考前一个GOP的信息
    int  b_bluray_compat;            //支持蓝光碟
    int  b_deblocking_filter;        //去块滤波开关
    int  i_deblocking_filter_alphac0;//[-6, 6] -6 light filter, 6 strong
    int  i_deblocking_filter_beta;   //[-6, 6] 同上
    int  b_cabac;                    //自适应算术编码cabac开关
    int  i_cabac_init_idc;           //给出算术编码初始化时表格的选择
    int  b_interlaced;               //隔行扫描
    int  b_constrained_intra;
    int  i_cqm_preset;               //自定义量化矩阵(CQM), 初始化量化模式为flat
    char *psz_cqm_file;              //读取JM格式的外部量化矩阵文件,忽略其他cqm选项
    uint8_t  cqm_4iy[16];            //used only if i_cqm_preset == X264_CQM_CUSTOM 
    uint8_t  cqm_4py[16];
    uint8_t  cqm_4ic[16];
    uint8_t  cqm_4pc[16];
    uint8_t  cqm_8iy[64];
    uint8_t  cqm_8py[64];
    uint8_t  cqm_8ic[64];
    uint8_t  cqm_8pc[64];
 
    void(*pf_log)(void *, int i_level, const char *psz, va_list);     //日志函数
    void  *p_log_private;
    int    i_log_level;             //日志级别,不需要打印编码信息时直接注释掉即可
    int    b_visualize;             //是否显示日志
    char   *psz_dump_yuv;           //重建帧的文件名
 
    struct
    {
        unsigned int intra;         //帧内分区
        unsigned int inter;         //帧间分区
        int  b_transform_8x8;
        int  i_weighted_pred;       //P帧权重
        int  b_weighted_bipred;     //B帧隐式加权
        int  i_direct_mv_pred;      //时间空间运动向量预测模式
        int  i_chroma_qp_offset;    //色度量化步长偏移量
        int  i_me_method;           //运动估计算法 (X264_ME_*)
        int  i_me_range;            //整像素运动估计搜索范围 (from predicted mv)
        int  i_mv_range;            //运动矢量最大长度. -1 = auto, based on level
        int  i_mv_range_thread;     //线程之间的最小运动向量缓冲.  -1 = auto, based on number of threads.
        int  i_subpel_refine;       //亚像素运动估计质量
        int  b_chroma_me;           //亚像素色度运动估计和P帧的模式选择
        int  b_mixed_references;    //允许每个宏块的分区有它自己的参考号
        int  i_trellis;             //Trellis量化提高效率,对每个8x8的块寻找合适的量化值
        int  b_fast_pskip;          //快速P帧跳过检测
        int  b_dct_decimate;        //P帧变换系数阈值
        int  i_noise_reduction;     //自适应伪盲区
        int  b_psy;                 //Psy优化开关,可能会增强细节
        float  f_psy_rd;            //Psy RD强度
        float  f_psy_trellis;       //Psy Trellis强度
        int  i_luma_deadzone[2];    //亮度量化中使用的盲区大小,{ 帧间, 帧内 }
        int  b_psnr;                //计算和打印PSNR信息
        int  b_ssim;                //计算和打印SSIM信息
    } analyse;                      //编码分析参数
 
    struct
    {
        int  i_rc_method;         //码率控制方式:X264_RC_CQP恒定质量,X264_RC_CRF恒定码率,  X264_RC_ABR平均码率
        int  i_qp_constant;       //指定P帧的量化值,0 - 51,0表示无损
        int  i_qp_min;            //允许的最小量化值,默认10
        int  i_qp_max;            //允许的最大量化值,默认51
        int  i_qp_step;           //量化步长,即相邻两帧之间量化值之差的最大值
        int   i_bitrate;          //平均码率大小
        float  f_rf_constant;     //1pass VBR, nominal QP. 实际质量,值越大图像越花,越小越清晰
        float  f_rf_constant_max; //最大码率因子                          
        float  f_rate_tolerance;  //允许的误差
        int    i_vbv_max_bitrate; //平均码率模式下,最大瞬时码率,默认0
        int    i_vbv_buffer_size; //码率控制缓冲区的大小,单位kbit,默认0
        float  f_vbv_buffer_init; //设置码率控制缓冲区(VBV)缓冲达到多满(百分比),才开始回放,范围0~1.0,默认0.9
        float  f_ip_factor;       //I帧和P帧之间的量化因子(QP)比值,默认1.4
        float  f_pb_factor;       //P帧和B帧之间的量化因子(QP)比值,默认1.3
        int   i_aq_mode;          //自适应量化(AQ)模式。0:关闭AQ;1:允许AQ在整个视频中和帧内重新分配码;2:自方差AQ(实验阶段),尝试逐帧调整强度。
        float  f_aq_strength;     //AQ强度,减少平趟和纹理区域的块效应和模糊度
        int   b_mb_tree;          //是否开启基于macroblock的qp控制方法
        int   i_lookahead;        //决定mbtree向前预测的帧数
        int   b_stat_write;       //是否将统计数据写入到文件psz_stat_out中
        char  *psz_stat_out;      //输出文件用于保存第一次编码统计数据
        int   b_stat_read;        //是否从文件psz_stat_in中读入统计数据
        char  *psz_stat_in;       //输入文件存有第一次编码的统计数据
        float  f_qcompress;       //量化曲线(quantizer curve)压缩因子。0.0 => 恒定比特率,1.0 => 恒定量化值
        float  f_qblur;           //时间上模糊量化,减少QP的波动(after curve compression)
        float  f_complexity_blur; //时间上模糊复杂性,减少QP的波动(before curve compression)
        x264_zone_t *zones;       //码率控制覆盖
        int    i_zones;           //number of zone_t's
        char  *psz_zones;         //指定区的另一种方法
    } rc;                         //码率控制参数
 
    //Muxing复用参数
    int  b_aud;                //生成访问单元分隔符
    int  b_repeat_headers;     //是否复制sps和pps放在每个关键帧的前面
    int  b_annexb;             //值为true,则NALU之前是4字节前缀码0x00000001;值为false,则NALU之前的4个字节为NALU长度
    int  i_sps_id;             //sps和pps的id号
    int  b_vfr_input;          //VFR输入。1 :时间基和时间戳用于码率控制  0 :仅帧率用于码率控制
    uint32_t  i_fps_num;       //帧率的分子
    uint32_t  i_fps_den;       //帧率的分母
    uint32_t  i_timebase_num;  //时间基的分子
    uint32_t  i_timebase_den;  //时间基的分母
    int  b_pulldown;
    int  b_pic_struct;         //强制在Picture Timing SEI传送pic_struct. 默认是未开启
    int b_fake_interlaced;
    int  i_slice_max_size;     //每个slice的最大字节数,包括预计的NAL开销
    int  i_slice_max_mbs;      //每个slice的最大宏块数,重写i_slice_count
    int  i_slice_count;        //每帧slice的数目,每个slice必须是矩形
} x264_param_t;

x264_nal_t:x264_nal_t里的数据在下一次调用x264_encoder_encode之后就无效了,因此要在调用或者使用之前使用它。

1
2
3
4
5
6
7
8
9
10
typedef struct
{
    int  i_ref_idc;        // Nal的优先级
    int  i_type;           // Nal的类型
    int  b_long_startcode; // 是否采用长前缀码0x00000001
    int  i_first_mb;       // 如果Nal为一条带,则表示该条带第一个宏块的指数
    int  i_last_mb;        // 如果Nal为一条带,则表示该条带最后一个宏块的指数
    int  i_payload;        // payload 的字节大小
    uint8_t *p_payload;    // 存放编码后的数据,已经封装成Nal单元
} x264_nal_t;

 

X264编码器有关的功能函数:

功能函数包括VCL编码和NAL打包。

VCL编码函数包括:

    创建编码器x264_encoder_open();

    编码图像x264_encoder_encode();

    关闭编码器x264_encoder_close();

NAL打包函数:

    x264_nal_encode();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//x264_picture_alloc:申请一帧图像空间,需要调用x264_picture_clean释放申请的内存
void x264_picture_alloc(x264_picture_t *pic, int i_csp, int i_width, int i_height);
//x264_picture_clean:释放x264_picture_alloc申请的有关资源,视频结构体是x264_picture_t
void x264_picture_clean(x264_picture_t *pic);
 
//x264_encoder_open:创建编码器句柄,读入x264_param_t的所有参数
x264_t *x264_encoder_open(x264_param_t*);
//x264_encoder_headers:写SPS和PPS数据
int x264_encoder_headers(x264_t*, x264_nal_t**, int*);
 
//x264_encoder_encode:编码一帧图像
int x264_encoder_encode(x264_t *, x264_nal_t **pp_nal, int *pi_nal,x264_picture_t *pic_in,x264_picture_t *pic_out);
//x264_encoder_close:关闭编码器句柄
void x264_encoder_close(x264_t*);
 
 
 
posted @   为取经而来  阅读(4353)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示