在前面的章节中,笔者有描述如何最简单的将一个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();