./x264 --help
Example usage:
Constant quality mode:
x264 --crf 24 -o <output> <input>
Two-pass with a bitrate of 1000kbps:
x264 --pass 1 --bitrate 1000 -o <output> <input>
x264 --pass 2 --bitrate 1000 -o <output> <input>
Lossless:
x264 --qp 0 -o <output> <input>
-b, --bframes <integer> Number of B-frames between I and P [3]
--b-adapt <integer> Adaptive B-frame decision method [1]
Higher values may lower threading efficiency.
- 0: Disabled
- 1: Fast
- 2: Optimal (slow with high --bframes)
--b-pyramid <string> Keep some B-frames as references [normal]
- none: Disabled
- strict: Strictly hierarchical pyramid
- normal: Non-strict (not Blu-ray compatible)
--open-gop Use recovery points to close GOPs
Only available with b-frames
--no-cabac Disable CABAC
--lookahead-threads <integer> Force a specific number of lookahead threads
Ratecontrol:
--crf <float> Quality-based VBR (0-51) [23.0]
bridge-far_qcif.yuv
bridge-far_qcif.264
raw [error]: raw input requires a resolution.
x264 [error]: could not open input file `bridge-far_qcif.yuv'
./x264 --help
x264编译运行
1) .configure
2) make
3)./x264 --crf 24 --no-cabac --input-res 1280x720 -o NBA.264 NBA.yuv
./x264 --threads 1 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 176x144 -o akiyo_qcif.264 akiyo_qcif.yuv
./x264 --crf 24 --no-cabac --input-res 176x144 -o akiyo_qcif.264 akiyo_qcif.yuv
./x264 --crf 24 --no-cabac --input-res 176x144 -o bridge-far_qcif.mkv bridge-far_qcif.yuv
./x264 --threads 1 --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 1280x720 -o Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.264 Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.yuv
./x264 --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 1280x720 -o Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.264 Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.yuv
./ffmpeg -threads 1 -i Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.264 Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.yuv
./x264 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 176x144 -o akiyo_qcif.264 akiyo_qcif.yuv
./x264 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 176x144 -o bridge-close_qcif.264 bridge-close_qcif.yuv
./x264 --threads 1 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 1280x720 -o NBA.264 NBA.yuv
./x264 --threads 1 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 1280x720 -o ../../video/NBA.264 ../../video/NBA.yuv
./x264 --threads 1 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 176x144 -o ../../video/akiyo_qcif.264 ../../video/akiyo_qcif.yuv
./x264 --scenecut 1500 --qp 28 --min-keyint 10000 --keyint 10000 --no-cabac --input-res 176x144 -o akiyo_qcif.264 akiyo_qcif.yuv
./x264 --scenecut 300 --qp 28 --min-keyint 10000 --keyint 10000 --no-cabac --input-res 1280x720 -o NBA.264 NBA.yuv
set args -threads 1 -i ../video/2.mp4 ../video/2.yuv
b libavcodec/h264_cavlc.c : 1217
set args -threads 1 -i akiyo_qcif.264 akiyo_qcif.yuv
b libavcodec/h264_cavlc.c:1821
1506
p tctrlInfoPack.ctrlInfo
(./x264 --help获得帮助)
scp local_file remote_username@remote_ip:remote_folder
set args -threads 1 -i ../video/bowing_qcif_300.264 ../video/bowing_qcif_300.yuv
set args -threads 1 -i NBA.264 NBA.yuv
b libavcodec/h264_cavlc.c : 781
下载x264链接:
http://www.videolan.org/developers/x264.html
ftp://ftp.videolan.org/pub/videolan/x264/snapshots/
./x264 --qp 0 --input-res 1920x1080 --no-cabac -o Madagascarlossless.mkv Madagascar.yuv
./x264 --crf 24 --input-res 1920x1080 -o Madagascarcabac.mkv Madagascar.yuv
源码分析:
参考http://www.cnblogs.com/chuncn/archive/2011/02/25/1964548.html
和流程图
x264_macroblock_write_cavlc函数分析:
http://blog.csdn.net/vblittleboy/article/details/7988066
x264.c main(); encode();
encode(); -> encode_frame();
encode_frame() -> x264_encoder_encode();
encoder.c x264_encoder_encode();
x264_encoder_encode() -> x264_slices_write();
x264_slices_write() -> x264_slice_write();
x264_slice_write() -> x264_macroblock_write_cavlc();
x264_slice_write() -> x264_macroblock_encode();
x264_slice_write() -> x264_macroblock_analyse();
Macroblock.c x264_macroblock_encode();
Analyse.c (encoder):void x264_macroblock_analyse( x264_t *h )
Analyse.c (encoder):x264_mb_analyse_intra()
//search x264_macroblock_encode
---- x264_macroblock_encode Matches (6 in 5 files) ----
Analyse.c (encoder): x264_macroblock_encode( h );
Encoder.c (encoder): x264_macroblock_encode( h );
Macroblock.c (encoder): * x264_macroblock_encode:
Macroblock.c (encoder):void x264_macroblock_encode( x264_t *h )
Macroblock.h (encoder):void x264_macroblock_encode ( x264_t *h );
Rdo.c (encoder): x264_macroblock_encode( h );
//Macroblock.c (encoder):
void x264_macroblock_encode( x264_t *h )
{
if( CHROMA444 )
x264_macroblock_encode_internal( h, 3, 0 );
else
x264_macroblock_encode_internal( h, 1, 1 );
}
void x264_macroblock_encode_internal() ->x264_mb_encode_i4x4()
Macroblock.h (encoder):static ALWAYS_INLINE void x264_mb_encode_i4x4( x264_t *h, int p, int idx, int i_qp, int i_mode, int b_predict )
//x264_mb_encode_i4x4重点函数 //正确
//search x264_mb_encode_i4x4
---- x264_mb_encode_i4x4 Matches (4 in 4 files) ----
Analyse.c (encoder): x264_mb_encode_i4x4( h, 0, idx, a->i_qp, a->i_predict4x4[idx], 0 );
Macroblock.c (encoder): x264_mb_encode_i4x4( h, p, i, i_qp, i_mode, 1 );
Macroblock.h (encoder):static ALWAYS_INLINE void x264_mb_encode_i4x4( x264_t *h, int p, int idx, int i_qp, int i_mode, int b_predict )
Rdo.c (encoder): x264_mb_encode_i4x4( h, p, i4, i_qp, i_mode, 1 );
cavlc.c x264_macroblock_write_cavlc();
x264_macroblock_write_cavlc() -> x264_cavlc_block_residual(),x264_cavlc_macroblock_luma_residual();
x264_cavlc_block_residual() -> x264_cavlc_block_residual_internal()
x264_cavlc_block_residual_internal();
#define x264_cavlc_block_residual(h,cat,idx,l)
static int x264_cavlc_block_residual_internal( x264_t *h, int ctx_block_cat, dctcoef *l, int nC )
重点函数:x264_cavlc_block_residual_internal();//错误
const vlc_t x264_coeff_token[6][16][4] ;
vlc_large_t x264_level_token[7][LEVEL_TABLE_SIZE];
#define bs_write_vlc(s,v) bs_write( s, (v).i_size, (v).i_bits )
static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
{
if( WORD_SIZE == 8 )
{
s->cur_bits = (s->cur_bits << i_count) | i_bits;
s->i_left -= i_count;
if( s->i_left <= 32 )
{
#if WORDS_BIGENDIAN
M32( s->p ) = s->cur_bits >> (32 - s->i_left);
#else
M32( s->p ) = endian_fix( s->cur_bits << s->i_left );
#endif
s->i_left += 32;
s->p += 4;
}
}
else
{
if( i_count < s->i_left )
{
s->cur_bits = (s->cur_bits << i_count) | i_bits;
s->i_left -= i_count;
}
else
{
i_count -= s->i_left;
s->cur_bits = (s->cur_bits << s->i_left) | (i_bits >> i_count);
M32( s->p ) = endian_fix( s->cur_bits );
s->p += 4;
s->cur_bits = i_bits;
s->i_left = 32 - i_count;
}
}
}
typedef struct bs_s
{
uint8_t *p_start;
uint8_t *p;
uint8_t *p_end;
uintptr_t cur_bits;
int i_left; /* i_count number of available bits */
int i_bits_encoded; /* RD only */
} bs_t;
typedef struct
{
int32_t last;
int32_t mask;
ALIGNED_16( dctcoef level[18] );//typedef int32_t dctcoef;
} x264_run_level_t;
x264_run_level_t runlevel;
runlevel比较重要。runlevel.level即那16个系数。
vlc_large_t x264_level_token[7][LEVEL_TABLE_SIZE];
typedef struct
{
uint16_t i_bits;
uint8_t i_size;
/* Next level table to use */
uint8_t i_next;
} vlc_large_t;
bs_write_vlc( s, x264_level_token[i_suffix_length][val] );
系数是runlevel.level[16]还是s->cur_bits还是x264_level_token[i_suffix_length][val].i_bits?
I16x16的dc和ac是要单独编码的 别的就不需要了
x264_cavlc_macroblock_luma_residual( h, plane_count );
->for( int p = 0; p < plane_count; p++ )
FOREACH_BIT( i8, 0, h->mb.i_cbp_luma )
for( int i4 = 0; i4 < 4; i4++ )
x264_cavlc_block_residual( h, DCT_LUMA_4x4, i4+i8*4+p*16, h->dct.luma4x4[i4+i8*4+p*16] );
参考帧顺序分析:
参考:
http://www.cnblogs.com/hatreds/archive/2012/04/26/2471137.html
http://www.nmm-hd.org/bbs/thread-1014-1-2.html(内容类似上面链接,重要)
/*******************************************************************
* x264_encoder_encode:
* XXX: i_poc : is the poc of the current given picture
* i_frame : is the number of the frame being coded
* ex: type frame poc
* I 0 2*0
* P 1 2*3
* B 2 2*1
* B 3 2*2
* P 4 2*6
* B 5 2*4
* B 6 2*5
********************************************************************
x264_param_t
X264.h:typedef struct x264_param_t
Analysis:
--weightp <integer> Weighted prediction for P-frames [2]
- 0: Disabled
- 1: Weighted refs
- 2: Weighted refs + Duplicates
不过在X264中,由于它本身尚不支持SVC,GOP被定义为IDR帧之间的距离
IDR有关的参数除了上面GOP设定的两个基本参数外,还有一个–scenecut
-b, --bframes <integer> Number of B-frames between I and P [3]
x264参考帧实验讨论
http://blog.csdn.net/wutong_login/article/details/5788643
参数解读
http://blog.163.com/cgq_i/blog/static/72877923201002922848510/
ffmpeg使用x264编码的配置(一)
http://xcshen.blog.51cto.com/2835389/624177
ffmpeg使用x264编码的配置(二)
http://xcshen.blog.51cto.com/2835389/624178
总的:
http://www.php-oa.com/2009/03/09/ffmpeg_x264.html
http://xcshen.blog.51cto.com/2835389/624180
源自FFmpeg项目组的两个视频编码:
Snow
FFV1
除此之外还有很多
参数设置
http://blog.csdn.net/newthinker_wei/article/details/8844042
源码分析:
Macroblock.h
static ALWAYS_INLINE void x264_mb_encode_i4x4( x264_t *h, int p, int idx, int i_qp, int i_mode, int b_predict )
int nz;
pixel *p_src = &h->mb.pic.p_fenc[p][block_idx_xy_fenc[idx]];
pixel *p_dst = &h->mb.pic.p_fdec[p][block_idx_xy_fdec[idx]];
ALIGNED_ARRAY_N( dctcoef, dct4x4,[16] );
if( b_predict )
{
if( h->mb.b_lossless )
x264_predict_lossless_4x4( h, p_dst, p, idx, i_mode );
else
h->predict_4x4[i_mode]( p_dst );
}
if( h->mb.b_lossless )
{
nz = h->zigzagf.sub_4x4( h->dct.luma4x4[p*16+idx], p_src, p_dst ); //z型扫描
h->mb.cache.non_zero_count[x264_scan8[p*16+idx]] = nz;
h->mb.i_cbp_luma |= nz<<(idx>>2);
return;
}
h->dctf.sub4x4_dct( dct4x4, p_src, p_dst ); //dct变换
nz = x264_quant_4x4( h, dct4x4, i_qp, ctx_cat_plane[DCT_LUMA_4x4][p], 1, p, idx ); //量化 后面添加自己代码
h->mb.cache.non_zero_count[x264_scan8[p*16+idx]] = nz;
if( nz )
{
h->mb.i_cbp_luma |= 1<<(idx>>2);
h->zigzagf.scan_4x4( h->dct.luma4x4[p*16+idx], dct4x4 ); //z型扫描
h->quantf.dequant_4x4( dct4x4, h->dequant4_mf[p?CQM_4IC:CQM_4IY], i_qp ); //反量化
h->dctf.add4x4_idct( p_dst, dct4x4 ); //反dct变换
}
}
#define ALIGNED_ARRAY_N ALIGNED_ARRAY_16
#if ARCH_ARM
#define ALIGNED_ARRAY_16( ... ) ALIGNED_ARRAY_EMU( 15, __VA_ARGS__ )
#else
#define ALIGNED_ARRAY_16( type, name, sub1, ... )\
ALIGNED_16( type name sub1 __VA_ARGS__ )
#endif
typedef int16_t dctcoef;
ALIGNED_ARRAY_N( dctcoef, dct4x4,[16] );
//上面一行等价与 dctcoef dct4x4[16]; //dctcoef==int16_t
//宏块类型
enum mb_class_e
{
I_4x4 = 0,
I_8x8 = 1,
I_16x16 = 2,
I_PCM = 3,
P_L0 = 4,
P_8x8 = 5,
P_SKIP = 6,
B_DIRECT = 7,
B_L0_L0 = 8,
B_L0_L1 = 9,
B_L0_BI = 10,
B_L1_L0 = 11,
B_L1_L1 = 12,
B_L1_BI = 13,
B_BI_L0 = 14,
B_BI_L1 = 15,
B_BI_BI = 16,
B_8x8 = 17,
B_SKIP = 18,
X264_MBTYPE_MAX = 19
};
enum mb_partition_e
{
/* sub partition type for P_8x8 and B_8x8 */
D_L0_4x4 = 0,
D_L0_8x4 = 1,
D_L0_4x8 = 2,
D_L0_8x8 = 3,
/* sub partition type for B_8x8 only */
D_L1_4x4 = 4,
D_L1_8x4 = 5,
D_L1_4x8 = 6,
D_L1_8x8 = 7,
D_BI_4x4 = 8,
D_BI_8x4 = 9,
D_BI_4x8 = 10,
D_BI_8x8 = 11,
D_DIRECT_8x8 = 12,
/* partition */
D_8x8 = 13,
D_16x8 = 14,
D_8x16 = 15,
D_16x16 = 16,
X264_PARTTYPE_MAX = 17,
};
//x264_macroblock_encode_internal()
if(I_PCM)
if(P_SKIP)
if(B_SKIP)
if(I_16x16)else if(I_8x8)else if(I_4x4) else...
/* encode chroma */
if( chroma )
//x264_mb_encode_i4x4重点函数在else if(I_4x4)中
//slice_type_e
enum slice_type_e
{
SLICE_TYPE_P = 0,
SLICE_TYPE_B = 1,
SLICE_TYPE_I = 2,
};
h->sh.i_type != SLICE_TYPE_I
x264_slice_header_t sh;
//x264_slice_header_t:
typedef struct
{
x264_sps_t *sps;
x264_pps_t *pps;
int i_type;
//common/osdep.h
#elif HAVE_POSIXTHREAD
#include <pthread.h>
#define x264_pthread_t pthread_t
#define x264_pthread_create pthread_create
#define x264_pthread_join pthread_join
#define x264_pthread_mutex_t pthread_mutex_t
#define x264_pthread_mutex_init pthread_mutex_init
#define x264_pthread_mutex_destroy pthread_mutex_destroy
#define x264_pthread_mutex_lock pthread_mutex_lock
#define x264_pthread_mutex_unlock pthread_mutex_unlock
#define x264_pthread_cond_t pthread_cond_t
#define x264_pthread_cond_init pthread_cond_init
#define x264_pthread_cond_destroy pthread_cond_destroy
#define x264_pthread_cond_broadcast pthread_cond_broadcast
#define x264_pthread_cond_wait pthread_cond_wait
#define x264_pthread_attr_t pthread_attr_t
#define x264_pthread_attr_init pthread_attr_init
#define x264_pthread_attr_destroy pthread_attr_destroy
#define x264_pthread_num_processors_np pthread_num_processors_np
#define X264_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
修改代码在4个位置:
encoder/macroblock.h
x264.c
x264.h
encoder/encoder.c:x264_encoder_open
//X264多线程分析
http://jmvc.blog.sohu.com/145356341.html
线程池
//线程函数
static void *x264_threadpool_thread( x264_threadpool_t *pool )
//创建线程
int x264_threadpool_init( x264_threadpool_t **p_pool, int threads,
void (*init_func)(void *), void *init_arg )
//加入运行的线程队列
void x264_threadpool_run( x264_threadpool_t *pool, void *(*func)(void *), void *arg )
//在进程运行函数x264_slices_write中开头加入线程锁,结尾释放线程锁。 从而保证线程同步。
加了之后虽然有多个线程,但是只有一个线程在解码。
如果在打印系数附近加锁,不能保证程序的顺序。只能保证操作的原子性。会引起嵌入错误,因为顺序是随机的。
//x264不需要定义。只需要在x264.h中声明就行了。
ffmpeg需要在avassert.h声明,在utils.h中定义。
//x264与ffmpeg dctdata的数据会错开。
//ffmpeg中h264_cavlc.c中莫名其妙库函数sqrt不能正确发挥作用。
i_cbp_chroma ,i_cbp_luma
Example usage:
Constant quality mode:
x264 --crf 24 -o <output> <input>
Two-pass with a bitrate of 1000kbps:
x264 --pass 1 --bitrate 1000 -o <output> <input>
x264 --pass 2 --bitrate 1000 -o <output> <input>
Lossless:
x264 --qp 0 -o <output> <input>
-b, --bframes <integer> Number of B-frames between I and P [3]
--b-adapt <integer> Adaptive B-frame decision method [1]
Higher values may lower threading efficiency.
- 0: Disabled
- 1: Fast
- 2: Optimal (slow with high --bframes)
--b-pyramid <string> Keep some B-frames as references [normal]
- none: Disabled
- strict: Strictly hierarchical pyramid
- normal: Non-strict (not Blu-ray compatible)
--open-gop Use recovery points to close GOPs
Only available with b-frames
--no-cabac Disable CABAC
--lookahead-threads <integer> Force a specific number of lookahead threads
Ratecontrol:
--crf <float> Quality-based VBR (0-51) [23.0]
bridge-far_qcif.yuv
bridge-far_qcif.264
raw [error]: raw input requires a resolution.
x264 [error]: could not open input file `bridge-far_qcif.yuv'
./x264 --help
x264编译运行
1) .configure
2) make
3)./x264 --crf 24 --no-cabac --input-res 1280x720 -o NBA.264 NBA.yuv
./x264 --threads 1 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 176x144 -o akiyo_qcif.264 akiyo_qcif.yuv
./x264 --crf 24 --no-cabac --input-res 176x144 -o akiyo_qcif.264 akiyo_qcif.yuv
./x264 --crf 24 --no-cabac --input-res 176x144 -o bridge-far_qcif.mkv bridge-far_qcif.yuv
./x264 --threads 1 --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 1280x720 -o Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.264 Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.yuv
./x264 --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 1280x720 -o Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.264 Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.yuv
./ffmpeg -threads 1 -i Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.264 Modern.Family.S04E01.720p.HDTV.X264-DIMENSION\ 00_00_00-00_00_20_track1_und.yuv
./x264 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 176x144 -o akiyo_qcif.264 akiyo_qcif.yuv
./x264 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 176x144 -o bridge-close_qcif.264 bridge-close_qcif.yuv
./x264 --threads 1 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 1280x720 -o NBA.264 NBA.yuv
./x264 --threads 1 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 1280x720 -o ../../video/NBA.264 ../../video/NBA.yuv
./x264 --threads 1 --profile baseline --log-level none --rc-lookahead 0 --fps 25 --output-csp i420 --keyint 25 --no-cabac --input-res 176x144 -o ../../video/akiyo_qcif.264 ../../video/akiyo_qcif.yuv
./x264 --scenecut 1500 --qp 28 --min-keyint 10000 --keyint 10000 --no-cabac --input-res 176x144 -o akiyo_qcif.264 akiyo_qcif.yuv
./x264 --scenecut 300 --qp 28 --min-keyint 10000 --keyint 10000 --no-cabac --input-res 1280x720 -o NBA.264 NBA.yuv
set args -threads 1 -i ../video/2.mp4 ../video/2.yuv
b libavcodec/h264_cavlc.c : 1217
set args -threads 1 -i akiyo_qcif.264 akiyo_qcif.yuv
b libavcodec/h264_cavlc.c:1821
1506
p tctrlInfoPack.ctrlInfo
(./x264 --help获得帮助)
scp local_file remote_username@remote_ip:remote_folder
set args -threads 1 -i ../video/bowing_qcif_300.264 ../video/bowing_qcif_300.yuv
set args -threads 1 -i NBA.264 NBA.yuv
b libavcodec/h264_cavlc.c : 781
下载x264链接:
http://www.videolan.org/developers/x264.html
ftp://ftp.videolan.org/pub/videolan/x264/snapshots/
./x264 --qp 0 --input-res 1920x1080 --no-cabac -o Madagascarlossless.mkv Madagascar.yuv
./x264 --crf 24 --input-res 1920x1080 -o Madagascarcabac.mkv Madagascar.yuv
源码分析:
参考http://www.cnblogs.com/chuncn/archive/2011/02/25/1964548.html
和流程图
x264_macroblock_write_cavlc函数分析:
http://blog.csdn.net/vblittleboy/article/details/7988066
x264.c main(); encode();
encode(); -> encode_frame();
encode_frame() -> x264_encoder_encode();
encoder.c x264_encoder_encode();
x264_encoder_encode() -> x264_slices_write();
x264_slices_write() -> x264_slice_write();
x264_slice_write() -> x264_macroblock_write_cavlc();
x264_slice_write() -> x264_macroblock_encode();
x264_slice_write() -> x264_macroblock_analyse();
Macroblock.c x264_macroblock_encode();
Analyse.c (encoder):void x264_macroblock_analyse( x264_t *h )
Analyse.c (encoder):x264_mb_analyse_intra()
//search x264_macroblock_encode
---- x264_macroblock_encode Matches (6 in 5 files) ----
Analyse.c (encoder): x264_macroblock_encode( h );
Encoder.c (encoder): x264_macroblock_encode( h );
Macroblock.c (encoder): * x264_macroblock_encode:
Macroblock.c (encoder):void x264_macroblock_encode( x264_t *h )
Macroblock.h (encoder):void x264_macroblock_encode ( x264_t *h );
Rdo.c (encoder): x264_macroblock_encode( h );
//Macroblock.c (encoder):
void x264_macroblock_encode( x264_t *h )
{
if( CHROMA444 )
x264_macroblock_encode_internal( h, 3, 0 );
else
x264_macroblock_encode_internal( h, 1, 1 );
}
void x264_macroblock_encode_internal() ->x264_mb_encode_i4x4()
Macroblock.h (encoder):static ALWAYS_INLINE void x264_mb_encode_i4x4( x264_t *h, int p, int idx, int i_qp, int i_mode, int b_predict )
//x264_mb_encode_i4x4重点函数 //正确
//search x264_mb_encode_i4x4
---- x264_mb_encode_i4x4 Matches (4 in 4 files) ----
Analyse.c (encoder): x264_mb_encode_i4x4( h, 0, idx, a->i_qp, a->i_predict4x4[idx], 0 );
Macroblock.c (encoder): x264_mb_encode_i4x4( h, p, i, i_qp, i_mode, 1 );
Macroblock.h (encoder):static ALWAYS_INLINE void x264_mb_encode_i4x4( x264_t *h, int p, int idx, int i_qp, int i_mode, int b_predict )
Rdo.c (encoder): x264_mb_encode_i4x4( h, p, i4, i_qp, i_mode, 1 );
cavlc.c x264_macroblock_write_cavlc();
x264_macroblock_write_cavlc() -> x264_cavlc_block_residual(),x264_cavlc_macroblock_luma_residual();
x264_cavlc_block_residual() -> x264_cavlc_block_residual_internal()
x264_cavlc_block_residual_internal();
#define x264_cavlc_block_residual(h,cat,idx,l)
static int x264_cavlc_block_residual_internal( x264_t *h, int ctx_block_cat, dctcoef *l, int nC )
重点函数:x264_cavlc_block_residual_internal();//错误
const vlc_t x264_coeff_token[6][16][4] ;
vlc_large_t x264_level_token[7][LEVEL_TABLE_SIZE];
#define bs_write_vlc(s,v) bs_write( s, (v).i_size, (v).i_bits )
static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
{
if( WORD_SIZE == 8 )
{
s->cur_bits = (s->cur_bits << i_count) | i_bits;
s->i_left -= i_count;
if( s->i_left <= 32 )
{
#if WORDS_BIGENDIAN
M32( s->p ) = s->cur_bits >> (32 - s->i_left);
#else
M32( s->p ) = endian_fix( s->cur_bits << s->i_left );
#endif
s->i_left += 32;
s->p += 4;
}
}
else
{
if( i_count < s->i_left )
{
s->cur_bits = (s->cur_bits << i_count) | i_bits;
s->i_left -= i_count;
}
else
{
i_count -= s->i_left;
s->cur_bits = (s->cur_bits << s->i_left) | (i_bits >> i_count);
M32( s->p ) = endian_fix( s->cur_bits );
s->p += 4;
s->cur_bits = i_bits;
s->i_left = 32 - i_count;
}
}
}
typedef struct bs_s
{
uint8_t *p_start;
uint8_t *p;
uint8_t *p_end;
uintptr_t cur_bits;
int i_left; /* i_count number of available bits */
int i_bits_encoded; /* RD only */
} bs_t;
typedef struct
{
int32_t last;
int32_t mask;
ALIGNED_16( dctcoef level[18] );//typedef int32_t dctcoef;
} x264_run_level_t;
x264_run_level_t runlevel;
runlevel比较重要。runlevel.level即那16个系数。
vlc_large_t x264_level_token[7][LEVEL_TABLE_SIZE];
typedef struct
{
uint16_t i_bits;
uint8_t i_size;
/* Next level table to use */
uint8_t i_next;
} vlc_large_t;
bs_write_vlc( s, x264_level_token[i_suffix_length][val] );
系数是runlevel.level[16]还是s->cur_bits还是x264_level_token[i_suffix_length][val].i_bits?
I16x16的dc和ac是要单独编码的 别的就不需要了
x264_cavlc_macroblock_luma_residual( h, plane_count );
->for( int p = 0; p < plane_count; p++ )
FOREACH_BIT( i8, 0, h->mb.i_cbp_luma )
for( int i4 = 0; i4 < 4; i4++ )
x264_cavlc_block_residual( h, DCT_LUMA_4x4, i4+i8*4+p*16, h->dct.luma4x4[i4+i8*4+p*16] );
参考帧顺序分析:
参考:
http://www.cnblogs.com/hatreds/archive/2012/04/26/2471137.html
http://www.nmm-hd.org/bbs/thread-1014-1-2.html(内容类似上面链接,重要)
/*******************************************************************
* x264_encoder_encode:
* XXX: i_poc : is the poc of the current given picture
* i_frame : is the number of the frame being coded
* ex: type frame poc
* I 0 2*0
* P 1 2*3
* B 2 2*1
* B 3 2*2
* P 4 2*6
* B 5 2*4
* B 6 2*5
********************************************************************
x264_param_t
X264.h:typedef struct x264_param_t
Analysis:
--weightp <integer> Weighted prediction for P-frames [2]
- 0: Disabled
- 1: Weighted refs
- 2: Weighted refs + Duplicates
不过在X264中,由于它本身尚不支持SVC,GOP被定义为IDR帧之间的距离
IDR有关的参数除了上面GOP设定的两个基本参数外,还有一个–scenecut
-b, --bframes <integer> Number of B-frames between I and P [3]
x264参考帧实验讨论
http://blog.csdn.net/wutong_login/article/details/5788643
参数解读
http://blog.163.com/cgq_i/blog/static/72877923201002922848510/
ffmpeg使用x264编码的配置(一)
http://xcshen.blog.51cto.com/2835389/624177
ffmpeg使用x264编码的配置(二)
http://xcshen.blog.51cto.com/2835389/624178
总的:
http://www.php-oa.com/2009/03/09/ffmpeg_x264.html
http://xcshen.blog.51cto.com/2835389/624180
源自FFmpeg项目组的两个视频编码:
Snow
FFV1
除此之外还有很多
参数设置
http://blog.csdn.net/newthinker_wei/article/details/8844042
源码分析:
Macroblock.h
static ALWAYS_INLINE void x264_mb_encode_i4x4( x264_t *h, int p, int idx, int i_qp, int i_mode, int b_predict )
int nz;
pixel *p_src = &h->mb.pic.p_fenc[p][block_idx_xy_fenc[idx]];
pixel *p_dst = &h->mb.pic.p_fdec[p][block_idx_xy_fdec[idx]];
ALIGNED_ARRAY_N( dctcoef, dct4x4,[16] );
if( b_predict )
{
if( h->mb.b_lossless )
x264_predict_lossless_4x4( h, p_dst, p, idx, i_mode );
else
h->predict_4x4[i_mode]( p_dst );
}
if( h->mb.b_lossless )
{
nz = h->zigzagf.sub_4x4( h->dct.luma4x4[p*16+idx], p_src, p_dst ); //z型扫描
h->mb.cache.non_zero_count[x264_scan8[p*16+idx]] = nz;
h->mb.i_cbp_luma |= nz<<(idx>>2);
return;
}
h->dctf.sub4x4_dct( dct4x4, p_src, p_dst ); //dct变换
nz = x264_quant_4x4( h, dct4x4, i_qp, ctx_cat_plane[DCT_LUMA_4x4][p], 1, p, idx ); //量化 后面添加自己代码
h->mb.cache.non_zero_count[x264_scan8[p*16+idx]] = nz;
if( nz )
{
h->mb.i_cbp_luma |= 1<<(idx>>2);
h->zigzagf.scan_4x4( h->dct.luma4x4[p*16+idx], dct4x4 ); //z型扫描
h->quantf.dequant_4x4( dct4x4, h->dequant4_mf[p?CQM_4IC:CQM_4IY], i_qp ); //反量化
h->dctf.add4x4_idct( p_dst, dct4x4 ); //反dct变换
}
}
#define ALIGNED_ARRAY_N ALIGNED_ARRAY_16
#if ARCH_ARM
#define ALIGNED_ARRAY_16( ... ) ALIGNED_ARRAY_EMU( 15, __VA_ARGS__ )
#else
#define ALIGNED_ARRAY_16( type, name, sub1, ... )\
ALIGNED_16( type name sub1 __VA_ARGS__ )
#endif
typedef int16_t dctcoef;
ALIGNED_ARRAY_N( dctcoef, dct4x4,[16] );
//上面一行等价与 dctcoef dct4x4[16]; //dctcoef==int16_t
//宏块类型
enum mb_class_e
{
I_4x4 = 0,
I_8x8 = 1,
I_16x16 = 2,
I_PCM = 3,
P_L0 = 4,
P_8x8 = 5,
P_SKIP = 6,
B_DIRECT = 7,
B_L0_L0 = 8,
B_L0_L1 = 9,
B_L0_BI = 10,
B_L1_L0 = 11,
B_L1_L1 = 12,
B_L1_BI = 13,
B_BI_L0 = 14,
B_BI_L1 = 15,
B_BI_BI = 16,
B_8x8 = 17,
B_SKIP = 18,
X264_MBTYPE_MAX = 19
};
enum mb_partition_e
{
/* sub partition type for P_8x8 and B_8x8 */
D_L0_4x4 = 0,
D_L0_8x4 = 1,
D_L0_4x8 = 2,
D_L0_8x8 = 3,
/* sub partition type for B_8x8 only */
D_L1_4x4 = 4,
D_L1_8x4 = 5,
D_L1_4x8 = 6,
D_L1_8x8 = 7,
D_BI_4x4 = 8,
D_BI_8x4 = 9,
D_BI_4x8 = 10,
D_BI_8x8 = 11,
D_DIRECT_8x8 = 12,
/* partition */
D_8x8 = 13,
D_16x8 = 14,
D_8x16 = 15,
D_16x16 = 16,
X264_PARTTYPE_MAX = 17,
};
//x264_macroblock_encode_internal()
if(I_PCM)
if(P_SKIP)
if(B_SKIP)
if(I_16x16)else if(I_8x8)else if(I_4x4) else...
/* encode chroma */
if( chroma )
//x264_mb_encode_i4x4重点函数在else if(I_4x4)中
//slice_type_e
enum slice_type_e
{
SLICE_TYPE_P = 0,
SLICE_TYPE_B = 1,
SLICE_TYPE_I = 2,
};
h->sh.i_type != SLICE_TYPE_I
x264_slice_header_t sh;
//x264_slice_header_t:
typedef struct
{
x264_sps_t *sps;
x264_pps_t *pps;
int i_type;
//common/osdep.h
#elif HAVE_POSIXTHREAD
#include <pthread.h>
#define x264_pthread_t pthread_t
#define x264_pthread_create pthread_create
#define x264_pthread_join pthread_join
#define x264_pthread_mutex_t pthread_mutex_t
#define x264_pthread_mutex_init pthread_mutex_init
#define x264_pthread_mutex_destroy pthread_mutex_destroy
#define x264_pthread_mutex_lock pthread_mutex_lock
#define x264_pthread_mutex_unlock pthread_mutex_unlock
#define x264_pthread_cond_t pthread_cond_t
#define x264_pthread_cond_init pthread_cond_init
#define x264_pthread_cond_destroy pthread_cond_destroy
#define x264_pthread_cond_broadcast pthread_cond_broadcast
#define x264_pthread_cond_wait pthread_cond_wait
#define x264_pthread_attr_t pthread_attr_t
#define x264_pthread_attr_init pthread_attr_init
#define x264_pthread_attr_destroy pthread_attr_destroy
#define x264_pthread_num_processors_np pthread_num_processors_np
#define X264_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
修改代码在4个位置:
encoder/macroblock.h
x264.c
x264.h
encoder/encoder.c:x264_encoder_open
//X264多线程分析
http://jmvc.blog.sohu.com/145356341.html
线程池
//线程函数
static void *x264_threadpool_thread( x264_threadpool_t *pool )
//创建线程
int x264_threadpool_init( x264_threadpool_t **p_pool, int threads,
void (*init_func)(void *), void *init_arg )
//加入运行的线程队列
void x264_threadpool_run( x264_threadpool_t *pool, void *(*func)(void *), void *arg )
//在进程运行函数x264_slices_write中开头加入线程锁,结尾释放线程锁。 从而保证线程同步。
加了之后虽然有多个线程,但是只有一个线程在解码。
如果在打印系数附近加锁,不能保证程序的顺序。只能保证操作的原子性。会引起嵌入错误,因为顺序是随机的。
//x264不需要定义。只需要在x264.h中声明就行了。
ffmpeg需要在avassert.h声明,在utils.h中定义。
//x264与ffmpeg dctdata的数据会错开。
//ffmpeg中h264_cavlc.c中莫名其妙库函数sqrt不能正确发挥作用。
i_cbp_chroma ,i_cbp_luma