x264学习

来源:互联网 发布:java实现两个线程并发 编辑:程序博客网 时间:2024/06/06 11:50
./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
0 0
原创粉丝点击