04-编码篇-X264的部分函数分析

发布时间:2024年01月15日

在前面的章节中,笔者有描述如何最简单的将一个YUV数据转换成H264,关于此代码涉及到如下结构体与函数,如下

x264_nal_t
x264_t
x264_picture_t
x264_param_t
x264_param_default();
x264_param_apply_profile();
x264_encoder_open();
x264_picture_init();
x264_picture_alloc();

x264_encoder_encode();
x264_picture_clean();
x264_encoder_close();

1.x264_picture_t 结构体描述一视频帧的特征,该结构体定义在x264.h中。

/********************************************************************************************
x264_picture_t 结构体描述一视频帧的特征,该结构体定义在x264.h中。
*********************************************************************************************/
typedef struct
{
int   i_type;            // 帧的类型,取值有X264_TYPE_KEYFRAME、X264_TYPE_P、
                            // X264_TYPE_AUTO等。初始化为auto,则在编码过程自行控制。
int   i_qpplus1;     // 此参数减1代表当前帧的量化参数值
int   i_pic_struct;  // 帧的结构类型,表示是帧还是场,是逐行还是隔行,
                           // 取值为枚举值 pic_struct_e,定义在x264.h中
int   b_keyframe; // 输出:是否是关键帧
int64_t   i_pts;     // 一帧的显示时间戳
int64_t   i_dts;     // 输出:解码时间戳。当一帧的pts非常接近0时,该dts值可能为负。

/* 编码器参数设置,如果为NULL则表示继续使用前一帧的设置。某些参数
   (例如aspect ratio) 由于收到H264本身的限制,只能每隔一个GOP才能改变。
   这种情况下,如果想让这些改变的参数立即生效,则必须强制生成一个IDR帧。*/ 
x264_param_t    *param;

x264_image_t     img;           // 存放一帧图像的真实数据
x264_image_properties_t    prop;
x264_hrd_t    hrd_timing;     // 输出:HRD时间信息,仅当i_nal_hrd设置了才有效
void    *opaque;                     // 私有数据存放区,将输入数据拷贝到输出帧中
} x264_picture_t ;

x264_nal_t中的数据在下一次调用x264_encoder_encode之后就无效了,因此必须在调用
x264_encoder_encode 或 x264_encoder_headers 之前使用或拷贝其中的数据。

/****************************************************************************************************************
x264_nal_t中的数据在下一次调用x264_encoder_encode之后就无效了,因此必须在调用
x264_encoder_encode 或 x264_encoder_headers 之前使用或拷贝其中的数据。
*****************************************************************************************************************/
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;

3.结构体x264_param_t定义在x264.h中

/****************************************************************************************************************
结构体x264_param_t定义在x264.h中
*****************************************************************************************************************/

typedef struct x264_param_t

{
    /* CPU 标志位 */
unsigned int cpu;
int  i_threads;                 // 并行编码多帧; 线程数,为0则自动多线程编码
int  b_sliced_threads;          // 如果为false,则一个slice只编码成一个NALU;
                                // 否则有几个线程,在编码成几个NALU。缺省为true。

int  b_deterministic; // 是否允许非确定性时线程优化
int  b_cpu_independent; // 强制采用典型行为,而不是采用独立于cpu的优化算法
int  i_sync_lookahead; // 线程超前缓存帧数

/* 视频属性 */
int  i_width; // 视频图像的宽
int  i_height; // 视频图像的高
int  i_csp;          // 编码比特流的CSP,仅支持i420,色彩空间设置
int  i_level_idc; // 指明作用的level值,可能与编码复杂度有关
int  i_frame_total;  // 编码帧的总数, 默认 0

/* hrd : hypothetical reference decoder (假定参考解码器) , 检验编码器产生的符合
  该标准的NAL单元流或字节流的偏差值。蓝光视频、电视广播及其它特殊领域有此要求 */
int  i_nal_hrd;

/* vui参数集 : 视频可用性信息、视频标准化选项 */
struct
{
    /* 宽高比的两个值相对互素,且在(0,  65535] 之间 */
    int  i_sar_height; // 样本宽高比的高度
int  i_sar_width;     // 样本宽高比的宽度
/* 0=undef, 1=no overscan, 2=overscan 过扫描线,
    默认"undef"(不设置),可选项:show(观看) / crop(去除) */
int  i_overscan;
/* 以下的值可以参见H264附录E */
int  i_vidformat;     // 视频在编码/数字化之前是什么类型,默认"undef".
                            // 取值有:Component, PAL, NTSC, SECAM, MAC 等
int  b_fullrange;           // 样本亮度和色度的计算方式,默认"off",可选项:off/on
int  i_colorprim;           // 原始色度格式,默认"undef"
int  i_transfer;            // 转换方式,默认"undef"
int  i_colmatrix;           // 设置从RGB计算得到亮度和色度所用的矩阵系数,默认"undef"
int  i_chroma_loc;          // 设置色度采样位置,范围0~5,默认0
} 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;                // Close GOP是指帧间的预测都是在GOP中进行的。
  // 使用Open GOP,后一个GOP会参考前一个GOP的信息。
int  b_bluray_compat;           // 支持蓝光碟

/* 去块滤波器需要的参数, alpha和beta是去块滤波器参数 */
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的块寻找合适的量化值,需要CABAC,
  // 0 :即关闭  1:只在最后编码时使用  2:在所有模式决策上启用
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;       // 最大码率因子,该选项仅在使用CRF并开启VBV时有效,
  // 图像质量的最大值,可能会导致VBV下溢。
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强度,减少平趟和纹理区域的块效应和模糊度
/* MBTree File是一个临时文件,记录了每个P帧中每个MB被参考的情况。
  目前mbtree只处理P帧的MB,同时也不支持b_pyramid. */
int   b_mb_tree;                // 是否开启基于macroblock的qp控制方法
int   i_lookahead;              // 决定mbtree向前预测的帧数

/* 2pass */
int   b_stat_write;             // 是否将统计数据写入到文件psz_stat_out中
char  *psz_stat_out;            // 输出文件用于保存第一次编码统计数据
int   b_stat_read;              // 是否从文件psz_stat_in中读入统计数据
char  *psz_stat_in;             // 输入文件存有第一次编码的统计数据
/* 2pass params (same as ffmpeg ones) */
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;

/* 裁剪矩形窗口参数:隐式添加到分辨率非16倍数的视频中 */
/* 在码流层指定一个切除(crop)矩形。若不想x264在编码时做crop,
   但希望解码器在回放时进行切除,可使用此项。单位为像素。 */
struct
{
unsigned int i_left;
    unsigned int i_top;
    unsigned int i_right;
    unsigned int i_bottom;
} crop_rect;

/* 编码3D视频时,此参数在码流中插入一个标志,告知解码器此3D视频是如何封装
  的。3D视频帧封装格式:帧封装、场交错、线交错、左右全景、左右半景、上下半
  景、L+深度、L+深度+图形+图形深度 */
int  i_frame_packing;
/* 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;       // 时间基的分母

/* 以某个预设模式将输入流(隔行,恒定帧率)标记为软交错(soft telecine)。默认none. 可用预设有:
  none, 22, 32, 64, double, triple, euro.  使用除none以外任一预设,都会连带开启--pic-struct */
int  b_pulldown;
int  b_pic_struct;  // 强制在Picture Timing SEI传送pic_struct. 默认是未开启
/* 将视频流标记为交错(隔行),哪怕并非为交错式编码。可用于编码蓝光兼容的25p和30p视频。默认是未开启 */
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;


4.x264_t是一个控制X264编码的全局性结构体,该结构体控制着视频一帧一帧的编码

/****************************************************************************************************************
x264_t是一个控制X264编码的全局性结构体,该结构体控制着视频一帧一帧的编码,
包括中间参考帧管理、码率控制、全局参数等一些重要参数和结构体。该结构体定义在common/common.h中,接下来我们详细分析该结构体的元素
*****************************************************************************************************************/
struct x264_t
{
/* encoder parameters */
x264_param_t    param; // 编码器编码参数,包括量化步长、编码级别等等一些参数

x264_t   *thread[X264_THREAD_MAX+1];
x264_t   *lookahead_thread[X264_LOOKAHEAD_THREAD_MAX];
int    b_thread_active;
int    i_thread_phase; /* which thread to use for the next frame */
int    i_thread_idx;   /* which thread this is */
int    i_threadslice_start; /* first row in this thread slice */
int    i_threadslice_end; /* row after the end of this thread slice */
int    i_threadslice_pass; /* which pass of encoding we are on */
x264_threadpool_t  *threadpool;
x264_threadpool_t  *lookaheadpool;
x264_pthread_mutex_t mutex;
x264_pthread_cond_t   cv;

 /* bitstream output */
struct
{
int    i_nal;
int    i_nals_allocated;
int    i_bitstream;       /* size of p_bitstream */
uint8_t   *p_bitstream;     /* will hold data for all nal */
bs_t  bs;
x264_nal_t  *nal;
} out;

uint8_t *nal_buffer;
int    nal_buffer_size;
int    reconfig;
x264_t  *reconfig_h;

/**** thread synchronization starts here ****/
/* frame number/poc */
int    i_frame;   // 编码帧号,用于计算POC(picture of count 标识视频帧的解码顺序)
int    i_frame_num;
int    i_thread_frames; // Number of different frames being encoded by threads;
// 1 when sliced-threads is on.
int         i_nal_type;   // Nal单元的类型,这些类型值定义在x264.h中,需要理解的类型有:
// 不分区(一帧作为一个片)非IDR图像的片;片分区A、片分区B、片分区C、
// IDR图像中的片、序列参数集、图像参数集
int         i_nal_ref_idc;   // Nal单元的优先级别,取值范围[0,1,2,3],值越大表示优先级越高,此Nal单元就越重要
int64_t   i_disp_fields; // Number of displayed fields (both coded and implied via pic_struct)
int         i_disp_fields_last_frame;
int64_t   i_prev_duration;   // Duration of previous frame
int64_t   i_coded_fields;   // Number of coded fields (both coded and implied via pic_struct)
int64_t   i_cpb_delay;   // Equal to number of fields preceding this field since last buffering_period SEI
int64_t   i_coded_fields_lookahead;   // Use separate counters for lookahead
int64_t   i_cpb_delay_lookahead;
int64_t   i_cpb_delay_pir_offset;
int64_t   i_cpb_delay_pir_offset_next;
int64_t   i_last_idr_pts;
int         b_queued_intra_refresh;
int         i_idr_pic_id;

/* quantization matrix for decoding, [cqm][qp%6][coef] */
int       (*dequant4_mf[4])[16];   /* [4][6][16] */
int       (*dequant8_mf[4])[64];   /* [4][6][64] */
/* quantization matrix for trellis, [cqm][qp][coef] */
int      (*unquant4_mf[4])[16];   /* [4][QP_MAX_SPEC][16] */
int      (*unquant8_mf[4])[64];   /* [4][QP_MAX_SPEC][64] */
/* quantization matrix for deadzone */
udctcoef        (*quant4_mf[4])[16];     /* [4][QP_MAX_SPEC][16] */
udctcoef        (*quant8_mf[4])[64];     /* [4][QP_MAX_SPEC][64] */
udctcoef        (*quant4_bias[4])[16];   /* [4][QP_MAX_SPEC][16] */
udctcoef        (*quant8_bias[4])[64];   /* [4][QP_MAX_SPEC][64] */
udctcoef        (*quant4_bias0[4])[16];     /* [4][QP_MAX_SPEC][16] */
udctcoef        (*quant8_bias0[4])[64];     /* [4][QP_MAX_SPEC][64] */
udctcoef        (*nr_offset_emergency)[4][64];

/* mv/ref cost arrays. */
uint16_t *cost_mv[QP_MAX+1];
uint16_t *cost_mv_fpel[QP_MAX+1][4];

/* includes both the nonlinear luma->chroma mapping and chroma_qp_offset */
const uint8_t   *chroma_qp_table; 

/* Slice header,条带头结构体定义在common/common.h中 */
x264_slice_header_t sh;

/* SPS / PPS,我们只是用一个sps和一个pps */
x264_sps_t   sps[1];
x264_pps_t   pps[1];

/* Slice header backup, for SEI_DEC_REF_PIC_MARKING */
int   b_sh_backup;
x264_slice_header_t sh_backup;

/* cabac context */
x264_cabac_t   cabac;

/* 指示和控制帧编码过程的结构 */
struct
{
/* Frames to be encoded (whose types have been decided) */
/* 这个结构体涉及到X264编码过程中的帧管理,理解这个结构体中的变量在编码标准的理论意义是非常重要的 */
x264_frame_t **current;   // 已确定帧类型,待编码帧,每一个GOP在编码前,每一帧的类型在编码前已经确定。
// 当进行编码时,从这里取出一帧数据
/* Unused frames: 0 = fenc, 1 = fdec */
x264_frame_t **unused[2];   // 这个数组用于回收那些在编码中分配的frame空间,
// 当有新的需要时,直接拿过来用,不用重新分配新的空间,提高效率
/* Unused blank frames (for duplicates) */
x264_frame_t **blank_unused;

/* frames used for reference + sentinels */
x264_frame_t *reference[X264_REF_MAX+2];   // 参考帧队列,注意参考帧都是重建帧

int  i_last_keyframe;   // Frame number of the last keyframe,上一个关键字的帧序号
int  i_last_idr;               // Frame number of the last IDR (not RP),上一个IDR帧的帧序号,
// 配合前面的i_frame,可以用来计算POC
int  i_poc_last_open_gop;   // Poc of the I frame of the last open-gop. The value is only assigned during the 
// period between that I frame and the next P or I frame, else -1
int  i_input;       // Number of input frames already accepted,已经接收的输入帧数
// frames结构体中i_input指示当前输入的帧的(播放顺序)序号。
int  i_max_dpb;   // Number of frames allocated in the decoded picture buffer
int  i_max_ref0;   // 最大前向参考帧数量
int  i_max_ref1;   // 最大后向参考帧数量
int  i_delay;     // Number of frames buffered for B reordering;缓存的帧数,用于B帧重排序
int  i_bframe_delay;
int64_t i_bframe_delay_time;
int64_t i_first_pts;
int64_t i_prev_reordered_pts[2];
int64_t i_largest_pts;
int64_t i_second_largest_pts;
int  b_have_lowres;     // Whether 1/2 resolution luma planes are being used,亮度是否使用半像素精度
int  b_have_sub8x8_esa;
} frames;   // 指示和控制帧编码过程的结构

/* current frame being encoded */
x264_frame_t    *fenc;   // 指向当前编码帧

/* frame being reconstructed */
x264_frame_t    *fdec;   // 指向当前重建帧,重建帧的帧号要比当前编码帧的帧号小1

/* references lists */
int    i_ref[2];   // i_ref[0]和i_ref[1]分别表示前向和后向参考帧的数量
int    b_ref_reorder[2];
x264_frame_t    *fref[2][X264_REF_MAX+3];   // fref[0]和fref[1]分别表示存放前向和后向参考帧的数组(参考帧均是重建帧)
x264_frame_t    *fref_nearest[2];
   
/* hrd */
int  initial_cpb_removal_delay;
int  initial_cpb_removal_delay_offset;
int64_t  i_reordered_pts_delay;

/* Current MB DCT coeffs */
struct
{
        ALIGNED_N( dctcoef luma16x16_dc[3][16] );
        ALIGNED_16( dctcoef chroma_dc[2][8] );
        // FIXME share memory?
        ALIGNED_N( dctcoef luma8x8[12][64] );
        ALIGNED_N( dctcoef luma4x4[16*3][16] );
} dct;
   /* MB table and cache for current frame/mb */
    struct
    {
        int     i_mb_width;
        int     i_mb_height;
        int     i_mb_count;                 /* number of mbs in a frame */

        /* Chroma subsampling */
        int     chroma_h_shift;
        int     chroma_v_shift;

        /* Strides */
        int     i_mb_stride;
        int     i_b8_stride;
        int     i_b4_stride;
        int     left_b8[2];
        int     left_b4[2];

        /* Current index */
        int     i_mb_x;
        int     i_mb_y;
        int     i_mb_xy;
        int     i_b8_xy;
        int     i_b4_xy;

        /* Search parameters */
        int     i_me_method;
        int     i_subpel_refine;
        int     b_chroma_me;
        int     b_trellis;
        int     b_noise_reduction;
        int     b_dct_decimate;
        int     i_psy_rd; /* Psy RD strength--fixed point value*/
        int     i_psy_trellis; /* Psy trellis strength--fixed point value*/

        int     b_interlaced;
        int     b_adaptive_mbaff; /* MBAFF+subme 0 requires non-adaptive MBAFF i.e. all field mbs */

        /* Allowed qpel MV range to stay within the picture + emulated edge pixels */
        int     mv_min[2];
        int     mv_max[2];
        int     mv_miny_row[3]; /* 0 == top progressive, 1 == bot progressive, 2 == interlaced */
        int     mv_maxy_row[3];
        /* Subpel MV range for motion search.
         * same mv_min/max but includes levels' i_mv_range. */
        int     mv_min_spel[2];
        int     mv_max_spel[2];
        int     mv_miny_spel_row[3];
        int     mv_maxy_spel_row[3];
        /* Fullpel MV range for motion search */
        ALIGNED_8( int16_t mv_limit_fpel[2][2] ); /* min_x, min_y, max_x, max_y */
        int     mv_miny_fpel_row[3];
        int     mv_maxy_fpel_row[3];

        /* neighboring MBs */
        unsigned int i_neighbour;
        unsigned int i_neighbour8[4];       /* neighbours of each 8x8 or 4x4 block that are available */
        unsigned int i_neighbour4[16];      /* at the time the block is coded */
        unsigned int i_neighbour_intra;     /* for constrained intra pred */
        unsigned int i_neighbour_frame;     /* ignoring slice boundaries */
        int     i_mb_type_top;
        int     i_mb_type_left[2];
        int     i_mb_type_topleft;
        int     i_mb_type_topright;
        int     i_mb_prev_xy;
        int     i_mb_left_xy[2];
        int     i_mb_top_xy;
        int     i_mb_topleft_xy;
        int     i_mb_topright_xy;
        int     i_mb_top_y;
        int     i_mb_topleft_y;
        int     i_mb_topright_y;
        const x264_left_table_t *left_index_table;
        int     i_mb_top_mbpair_xy;
        int     topleft_partition;
        int     b_allow_skip;
        int     field_decoding_flag;

        /**** thread synchronization ends here ****/
        /* subsequent variables are either thread-local or constant,
         * and won't be copied from one thread to another */

        /* mb table */
        uint8_t *base;                      /* base pointer for all malloced data in this mb */
        int8_t  *type;                      /* mb type */
        uint8_t *partition;                 /* mb partition */
        int8_t  *qp;                        /* mb qp */
        int16_t *cbp;                       /* mb cbp: 0x0?: luma, 0x?0: chroma, 0x100: luma dc, 0x200 and 0x400: chroma dc, 0x1000 PCM (all set for PCM) */
        int8_t  (*intra4x4_pred_mode)[8];   /* intra4x4 pred mode. for non I4x4 set to I_PRED_4x4_DC(2) */
                                            /* actually has only 7 entries; set to 8 for write-combining optimizations */
        uint8_t (*non_zero_count)[16*3];    /* nzc. for I_PCM set to 16 */
        int8_t  *chroma_pred_mode;          /* chroma_pred_mode. cabac only. for non intra I_PRED_CHROMA_DC(0) */
        int16_t (*mv[2])[2];                /* mb mv. set to 0 for intra mb */
        uint8_t (*mvd[2])[8][2];            /* absolute value of mb mv difference with predict, clipped to [0,33]. set to 0 if intra. cabac only */
        int8_t   *ref[2];                   /* mb ref. set to -1 if non used (intra or Lx only) */
        int16_t (*mvr[2][X264_REF_MAX*2])[2];/* 16x16 mv for each possible ref */
        int8_t  *skipbp;                    /* block pattern for SKIP or DIRECT (sub)mbs. B-frames + cabac only */
        int8_t  *mb_transform_size;         /* transform_size_8x8_flag of each mb */
        int32_t *slice_table;               /* sh->first_mb of the slice that the indexed mb is part of */
        uint8_t *field;

         /* buffer for weighted versions of the reference frames */
        pixel *p_weight_buf[X264_REF_MAX];

        /* current value */
        int     i_type;
        int     i_partition;
        ALIGNED_4( uint8_t i_sub_partition[4] );
        int     b_transform_8x8;

        int     i_cbp_luma;
        int     i_cbp_chroma;

        int     i_intra16x16_pred_mode;
        int     i_chroma_pred_mode;

        /* skip flags for i4x4 and i8x8
         * 0 = encode as normal.
         * 1 (non-RD only) = the DCT is still in h->dct, restore fdec and skip reconstruction.
         * 2 (RD only) = the DCT has since been overwritten by RD; restore that too. */
        int i_skip_intra;
        /* skip flag for motion compensation */
        /* if we've already done MC, we don't need to do it again */
        int b_skip_mc;
        /* set to true if we are re-encoding a macroblock. */
        int b_reencode_mb;
        int ip_offset; /* Used by PIR to offset the quantizer of intra-refresh blocks. */
        int b_deblock_rdo;
        int b_overflow; /* If CAVLC had a level code overflow during bitstream writing. */

        struct
        {
            /* space for p_fenc and p_fdec */
#define FENC_STRIDE 16
#define FDEC_STRIDE 32
            ALIGNED_64( pixel fenc_buf[48*FENC_STRIDE] );
            ALIGNED_64( pixel fdec_buf[54*FDEC_STRIDE] );

            /* i4x4 and i8x8 backup data, for skipping the encode stage when possible */
            ALIGNED_32( pixel i4x4_fdec_buf[16*16] );
            ALIGNED_32( pixel i8x8_fdec_buf[16*16] );
            ALIGNED_64( dctcoef i8x8_dct_buf[3][64] );
            ALIGNED_64( dctcoef i4x4_dct_buf[15][16] );
            uint32_t i4x4_nnz_buf[4];
            uint32_t i8x8_nnz_buf[4];

            /* Psy trellis DCT data */
            ALIGNED_64( dctcoef fenc_dct8[4][64] );
            ALIGNED_64( dctcoef fenc_dct4[16][16] );

            /* Psy RD SATD/SA8D scores cache */
            ALIGNED_64( uint32_t fenc_satd_cache[32] );
            ALIGNED_16( uint64_t fenc_hadamard_cache[9] );

            int i4x4_cbp;
            int i8x8_cbp;

            /* pointer over mb of the frame to be compressed */
            pixel *p_fenc[3]; /* y,u,v */
            /* pointer to the actual source frame, not a block copy */
            pixel *p_fenc_plane[3];

            /* pointer over mb of the frame to be reconstructed  */
            pixel *p_fdec[3];

            /* pointer over mb of the references */
            int i_fref[2];
            /* [12]: yN, yH, yV, yHV, (NV12 ? uv : I444 ? (uN, uH, uV, uHV, vN, ...)) */
            pixel *p_fref[2][X264_REF_MAX*2][12];
            pixel *p_fref_w[X264_REF_MAX*2];  /* weighted fullpel luma */
            uint16_t *p_integral[2][X264_REF_MAX];

            /* fref stride */
            int     i_stride[3];
        } pic;

        /* cache */
        struct
        {
            /* real intra4x4_pred_mode if I_4X4 or I_8X8, I_PRED_4x4_DC if mb available, -1 if not */
            ALIGNED_16( int8_t intra4x4_pred_mode[X264_SCAN8_LUMA_SIZE] );

            /* i_non_zero_count if available else 0x80. intentionally misaligned by 8 for asm */
            ALIGNED_8( uint8_t non_zero_count[X264_SCAN8_SIZE] );

            /* -1 if unused, -2 if unavailable */
            ALIGNED_4( int8_t ref[2][X264_SCAN8_LUMA_SIZE] );

            /* 0 if not available */
            ALIGNED_16( int16_t mv[2][X264_SCAN8_LUMA_SIZE][2] );
            ALIGNED_8( uint8_t mvd[2][X264_SCAN8_LUMA_SIZE][2] );

            /* 1 if SKIP or DIRECT. set only for B-frames + CABAC */
            ALIGNED_4( int8_t skip[X264_SCAN8_LUMA_SIZE] );

            ALIGNED_4( int16_t direct_mv[2][4][2] );
            ALIGNED_4( int8_t  direct_ref[2][4] );
            int     direct_partition;
            ALIGNED_4( int16_t pskip_mv[2] );

            /* number of neighbors (top and left) that used 8x8 dct */
            int     i_neighbour_transform_size;
            int     i_neighbour_skip;

            /* neighbor CBPs */
            int     i_cbp_top;
            int     i_cbp_left;

            /* extra data required for mbaff in mv prediction */
            int16_t topright_mv[2][3][2];
            int8_t  topright_ref[2][3];

            /* current mb deblock strength */
            uint8_t (*deblock_strength)[8][4];
        } cache;

        /* */
        int     i_qp;       /* current qp */
        int     i_chroma_qp;
        int     i_last_qp;  /* last qp */
        int     i_last_dqp; /* last delta qp */
        int     b_variable_qp; /* whether qp is allowed to vary per macroblock */
        int     b_lossless;
        int     b_direct_auto_read; /* take stats for --direct auto from the 2pass log */
        int     b_direct_auto_write; /* analyse direct modes, to use and/or save */

        /* lambda values */
        int     i_trellis_lambda2[2][2]; /* [luma,chroma][inter,intra] */
        int     i_psy_rd_lambda;
        int     i_chroma_lambda2_offset;

        /* B_direct and weighted prediction */
        int16_t dist_scale_factor_buf[2][2][X264_REF_MAX*2][4];
        int16_t (*dist_scale_factor)[4];
        int8_t bipred_weight_buf[2][2][X264_REF_MAX*2][4];
        int8_t (*bipred_weight)[4];
        /* maps fref1[0]'s ref indices into the current list0 */
#define map_col_to_list0(col) h->mb.map_col_to_list0[(col)+2]
        int8_t  map_col_to_list0[X264_REF_MAX+2];
        int ref_blind_dupe; /* The index of the blind reference frame duplicate. */
        int8_t deblock_ref_table[X264_REF_MAX*2+2];
#define deblock_ref_table(x) h->mb.deblock_ref_table[(x)+2]
    } mb;

    /* rate control encoding only */
    x264_ratecontrol_t *rc;

    /* stats */
    struct
    {
        /* Cumulated stats */

        /* per slice info */
        int     i_frame_count[3];
        int64_t i_frame_size[3];
        double  f_frame_qp[3];
        int     i_consecutive_bframes[X264_BFRAME_MAX+1];
        /* */
        double  f_ssd_global[3];
        double  f_psnr_average[3];
        double  f_psnr_mean_y[3];
        double  f_psnr_mean_u[3];
        double  f_psnr_mean_v[3];
        double  f_ssim_mean_y[3];
        double  f_frame_duration[3];
        /* */
        int64_t i_mb_count[3][19];
        int64_t i_mb_partition[2][17];
        int64_t i_mb_count_8x8dct[2];
        int64_t i_mb_count_ref[2][2][X264_REF_MAX*2];
        int64_t i_mb_cbp[6];
        int64_t i_mb_pred_mode[4][13];
        int64_t i_mb_field[3];
        /* */
        int     i_direct_score[2];
        int     i_direct_frames[2];
        /* num p-frames weighted */
        int     i_wpred[2];

        /* Current frame stats */
        x264_frame_stat_t frame;
    } stat;

    /* 0 = luma 4x4, 1 = luma 8x8, 2 = chroma 4x4, 3 = chroma 8x8 */
    udctcoef (*nr_offset)[64];
    uint32_t (*nr_residual_sum)[64];
    uint32_t *nr_count;

    ALIGNED_32( udctcoef nr_offset_denoise[4][64] );
    ALIGNED_32( uint32_t nr_residual_sum_buf[2][4][64] );
    uint32_t nr_count_buf[2][4];

    uint8_t luma2chroma_pixel[7]; /* Subsampled pixel size */

    /* Buffers that are allocated per-thread even in sliced threads. */
    void *scratch_buffer; /* for any temporary storage that doesn't want repeated malloc */
    void *scratch_buffer2; /* if the first one's already in use */
    pixel *intra_border_backup[5][3]; /* bottom pixels of the previous mb row, used for intra prediction after the framebuffer has been deblocked */
    /* Deblock strength values are stored for each 4x4 partition. In MBAFF
     * there are four extra values that need to be stored, located in [4][i]. */
    uint8_t (*deblock_strength[2])[2][8][4];

    /* CPU functions dependents */
    x264_predict_t      predict_16x16[4+3];
    x264_predict8x8_t   predict_8x8[9+3];
    x264_predict_t      predict_4x4[9+3];
    x264_predict_t      predict_chroma[4+3];
    x264_predict_t      predict_8x8c[4+3];
    x264_predict_t      predict_8x16c[4+3];
    x264_predict_8x8_filter_t predict_8x8_filter;

    x264_pixel_function_t pixf;
    x264_mc_functions_t   mc;
    x264_dct_function_t   dctf;
    x264_zigzag_function_t zigzagf;
    x264_zigzag_function_t zigzagf_interlaced;
    x264_zigzag_function_t zigzagf_progressive;
    x264_quant_function_t quantf;
    x264_deblock_function_t loopf;
    x264_bitstream_function_t bsf;

    x264_lookahead_t *lookahead;

#if HAVE_OPENCL
    x264_opencl_t opencl;
#endif
};

相关的函数API对应的功能,如下所示

//设置参数集结构体x264_param_t的缺省值
x264_param_default();
//打开编码器
x264_encoder_open();
//初始化
x264_picture_init();
//为图像结构体x264_picture_t分配内存
x264_picture_alloc();
//编码一帧图像
x264_encoder_encode();
//释放x264_picture_alloc()申请的资源
x264_picture_clean();
//关闭编码器
x264_encoder_close();

文章来源:https://blog.csdn.net/sishen4199/article/details/135548581
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。