Commit dd713cae authored by Henrik Gramner's avatar Henrik Gramner Committed by Fiona Glaser

Allow setting a chroma format at compile time

Gives a slight speed increase and significant binary size reduction when only one chroma format is needed.
parent 68f6db44
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
const int x264_bit_depth = BIT_DEPTH; const int x264_bit_depth = BIT_DEPTH;
const int x264_chroma_format = X264_CHROMA_FORMAT;
static void x264_log_default( void *, int, const char *, va_list ); static void x264_log_default( void *, int, const char *, va_list );
/**************************************************************************** /****************************************************************************
...@@ -52,7 +54,7 @@ void x264_param_default( x264_param_t *param ) ...@@ -52,7 +54,7 @@ void x264_param_default( x264_param_t *param )
param->i_sync_lookahead = X264_SYNC_LOOKAHEAD_AUTO; param->i_sync_lookahead = X264_SYNC_LOOKAHEAD_AUTO;
/* Video properties */ /* Video properties */
param->i_csp = X264_CSP_I420; param->i_csp = X264_CHROMA_FORMAT ? X264_CHROMA_FORMAT : X264_CSP_I420;
param->i_width = 0; param->i_width = 0;
param->i_height = 0; param->i_height = 0;
param->vui.i_sar_width = 0; param->vui.i_sar_width = 0;
......
...@@ -40,9 +40,6 @@ ...@@ -40,9 +40,6 @@
#define IS_DISPOSABLE(type) ( type == X264_TYPE_B ) #define IS_DISPOSABLE(type) ( type == X264_TYPE_B )
#define FIX8(f) ((int)(f*(1<<8)+.5)) #define FIX8(f) ((int)(f*(1<<8)+.5))
#define ALIGN(x,a) (((x)+((a)-1))&~((a)-1)) #define ALIGN(x,a) (((x)+((a)-1))&~((a)-1))
#define CHROMA_FORMAT h->sps->i_chroma_format_idc
#define CHROMA_SIZE(s) ((s)>>(h->mb.chroma_h_shift+h->mb.chroma_v_shift))
#define FRAME_SIZE(s) ((s)+2*CHROMA_SIZE(s))
#define CHECKED_MALLOC( var, size )\ #define CHECKED_MALLOC( var, size )\
do {\ do {\
...@@ -105,6 +102,17 @@ do {\ ...@@ -105,6 +102,17 @@ do {\
# define PARAM_INTERLACED 0 # define PARAM_INTERLACED 0
#endif #endif
#ifdef CHROMA_FORMAT
# define CHROMA_H_SHIFT (CHROMA_FORMAT == CHROMA_420 || CHROMA_FORMAT == CHROMA_422)
# define CHROMA_V_SHIFT (CHROMA_FORMAT == CHROMA_420)
#else
# define CHROMA_FORMAT h->sps->i_chroma_format_idc
# define CHROMA_H_SHIFT h->mb.chroma_h_shift
# define CHROMA_V_SHIFT h->mb.chroma_v_shift
#endif
#define CHROMA_SIZE(s) ((s)>>(CHROMA_H_SHIFT+CHROMA_V_SHIFT))
#define FRAME_SIZE(s) ((s)+2*CHROMA_SIZE(s))
#define CHROMA444 (CHROMA_FORMAT == CHROMA_444) #define CHROMA444 (CHROMA_FORMAT == CHROMA_444)
/* Unions for type-punning. /* Unions for type-punning.
......
...@@ -394,7 +394,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y ) ...@@ -394,7 +394,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
int stridey = h->fdec->i_stride[0]; int stridey = h->fdec->i_stride[0];
int strideuv = h->fdec->i_stride[1]; int strideuv = h->fdec->i_stride[1];
int chroma444 = CHROMA444; int chroma444 = CHROMA444;
int chroma_height = 16 >> h->mb.chroma_v_shift; int chroma_height = 16 >> CHROMA_V_SHIFT;
intptr_t uvdiff = chroma444 ? h->fdec->plane[2] - h->fdec->plane[1] : 1; intptr_t uvdiff = chroma444 ? h->fdec->plane[2] - h->fdec->plane[1] : 1;
for( int mb_x = 0; mb_x < h->mb.i_mb_width; mb_x += (~b_interlaced | mb_y)&1, mb_y ^= b_interlaced ) for( int mb_x = 0; mb_x < h->mb.i_mb_width; mb_x += (~b_interlaced | mb_y)&1, mb_y ^= b_interlaced )
...@@ -484,7 +484,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y ) ...@@ -484,7 +484,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
} }
int offy = MB_INTERLACED ? 4 : 0; int offy = MB_INTERLACED ? 4 : 0;
int offuv = MB_INTERLACED ? 4-h->mb.chroma_v_shift : 0; int offuv = MB_INTERLACED ? 4-CHROMA_V_SHIFT : 0;
left_qp[1] = h->mb.qp[h->mb.i_mb_left_xy[1]]; left_qp[1] = h->mb.qp[h->mb.i_mb_left_xy[1]];
luma_qp[1] = (qp + left_qp[1] + 1) >> 1; luma_qp[1] = (qp + left_qp[1] + 1) >> 1;
chroma_qp[1] = (qpc + h->chroma_qp_table[left_qp[1]] + 1) >> 1; chroma_qp[1] = (qpc + h->chroma_qp_table[left_qp[1]] + 1) >> 1;
......
...@@ -373,7 +373,7 @@ int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src ) ...@@ -373,7 +373,7 @@ int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
} }
else else
{ {
int v_shift = h->mb.chroma_v_shift; int v_shift = CHROMA_V_SHIFT;
get_plane_ptr( h, src, &pix[0], &stride[0], 0, 0, 0 ); get_plane_ptr( h, src, &pix[0], &stride[0], 0, 0, 0 );
h->mc.plane_copy( dst->plane[0], dst->i_stride[0], (pixel*)pix[0], h->mc.plane_copy( dst->plane[0], dst->i_stride[0], (pixel*)pix[0],
stride[0]/sizeof(pixel), h->param.i_width, h->param.i_height ); stride[0]/sizeof(pixel), h->param.i_width, h->param.i_height );
...@@ -486,8 +486,8 @@ void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_e ...@@ -486,8 +486,8 @@ void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_e
return; return;
for( int i = 0; i < frame->i_plane; i++ ) for( int i = 0; i < frame->i_plane; i++ )
{ {
int h_shift = i && h->mb.chroma_h_shift; int h_shift = i && CHROMA_H_SHIFT;
int v_shift = i && h->mb.chroma_v_shift; int v_shift = i && CHROMA_V_SHIFT;
int stride = frame->i_stride[i]; int stride = frame->i_stride[i];
int width = 16*h->mb.i_mb_width; int width = 16*h->mb.i_mb_width;
int height = (b_end ? 16*(h->mb.i_mb_height - mb_y) >> SLICE_MBAFF : 16) >> v_shift; int height = (b_end ? 16*(h->mb.i_mb_height - mb_y) >> SLICE_MBAFF : 16) >> v_shift;
...@@ -554,9 +554,9 @@ void x264_frame_expand_border_lowres( x264_frame_t *frame ) ...@@ -554,9 +554,9 @@ void x264_frame_expand_border_lowres( x264_frame_t *frame )
void x264_frame_expand_border_chroma( x264_t *h, x264_frame_t *frame, int plane ) void x264_frame_expand_border_chroma( x264_t *h, x264_frame_t *frame, int plane )
{ {
int v_shift = h->mb.chroma_v_shift; int v_shift = CHROMA_V_SHIFT;
plane_expand_border( frame->plane[plane], frame->i_stride[plane], 16*h->mb.i_mb_width, 16*h->mb.i_mb_height>>v_shift, plane_expand_border( frame->plane[plane], frame->i_stride[plane], 16*h->mb.i_mb_width, 16*h->mb.i_mb_height>>v_shift,
PADH, PADV>>v_shift, 1, 1, h->mb.chroma_h_shift ); PADH, PADV>>v_shift, 1, 1, CHROMA_H_SHIFT );
} }
void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame ) void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
...@@ -564,8 +564,8 @@ void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame ) ...@@ -564,8 +564,8 @@ void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
for( int i = 0; i < frame->i_plane; i++ ) for( int i = 0; i < frame->i_plane; i++ )
{ {
int i_width = h->param.i_width; int i_width = h->param.i_width;
int h_shift = i && h->mb.chroma_h_shift; int h_shift = i && CHROMA_H_SHIFT;
int v_shift = i && h->mb.chroma_v_shift; int v_shift = i && CHROMA_V_SHIFT;
int i_height = h->param.i_height >> v_shift; int i_height = h->param.i_height >> v_shift;
int i_padx = (h->mb.i_mb_width * 16 - h->param.i_width); int i_padx = (h->mb.i_mb_width * 16 - h->param.i_width);
int i_pady = (h->mb.i_mb_height * 16 - h->param.i_height) >> v_shift; int i_pady = (h->mb.i_mb_height * 16 - h->param.i_height) >> v_shift;
...@@ -591,7 +591,7 @@ void x264_expand_border_mbpair( x264_t *h, int mb_x, int mb_y ) ...@@ -591,7 +591,7 @@ void x264_expand_border_mbpair( x264_t *h, int mb_x, int mb_y )
{ {
for( int i = 0; i < h->fenc->i_plane; i++ ) for( int i = 0; i < h->fenc->i_plane; i++ )
{ {
int v_shift = i && h->mb.chroma_v_shift; int v_shift = i && CHROMA_V_SHIFT;
int stride = h->fenc->i_stride[i]; int stride = h->fenc->i_stride[i];
int height = h->param.i_height >> v_shift; int height = h->param.i_height >> v_shift;
int pady = (h->mb.i_mb_height * 16 - h->param.i_height) >> v_shift; int pady = (h->mb.i_mb_height * 16 - h->param.i_height) >> v_shift;
......
...@@ -51,7 +51,7 @@ static NOINLINE void x264_mb_mc_0xywh( x264_t *h, int x, int y, int width, int h ...@@ -51,7 +51,7 @@ static NOINLINE void x264_mb_mc_0xywh( x264_t *h, int x, int y, int width, int h
} }
else else
{ {
int v_shift = h->mb.chroma_v_shift; int v_shift = CHROMA_V_SHIFT;
// Chroma in 4:2:0 is offset if MCing from a field of opposite parity // Chroma in 4:2:0 is offset if MCing from a field of opposite parity
if( v_shift & MB_INTERLACED & i_ref ) if( v_shift & MB_INTERLACED & i_ref )
mvy += (h->mb.i_mb_y & 1)*4 - 2; mvy += (h->mb.i_mb_y & 1)*4 - 2;
...@@ -90,7 +90,7 @@ static NOINLINE void x264_mb_mc_1xywh( x264_t *h, int x, int y, int width, int h ...@@ -90,7 +90,7 @@ static NOINLINE void x264_mb_mc_1xywh( x264_t *h, int x, int y, int width, int h
} }
else else
{ {
int v_shift = h->mb.chroma_v_shift; int v_shift = CHROMA_V_SHIFT;
if( v_shift & MB_INTERLACED & i_ref ) if( v_shift & MB_INTERLACED & i_ref )
mvy += (h->mb.i_mb_y & 1)*4 - 2; mvy += (h->mb.i_mb_y & 1)*4 - 2;
...@@ -135,7 +135,7 @@ static NOINLINE void x264_mb_mc_01xywh( x264_t *h, int x, int y, int width, int ...@@ -135,7 +135,7 @@ static NOINLINE void x264_mb_mc_01xywh( x264_t *h, int x, int y, int width, int
} }
else else
{ {
int v_shift = h->mb.chroma_v_shift; int v_shift = CHROMA_V_SHIFT;
if( v_shift & MB_INTERLACED & i_ref0 ) if( v_shift & MB_INTERLACED & i_ref0 )
mvy0 += (h->mb.i_mb_y & 1)*4 - 2; mvy0 += (h->mb.i_mb_y & 1)*4 - 2;
if( v_shift & MB_INTERLACED & i_ref1 ) if( v_shift & MB_INTERLACED & i_ref1 )
...@@ -541,7 +541,7 @@ void x264_prefetch_fenc( x264_t *h, x264_frame_t *fenc, int i_mb_x, int i_mb_y ) ...@@ -541,7 +541,7 @@ void x264_prefetch_fenc( x264_t *h, x264_frame_t *fenc, int i_mb_x, int i_mb_y )
int stride_y = fenc->i_stride[0]; int stride_y = fenc->i_stride[0];
int stride_uv = fenc->i_stride[1]; int stride_uv = fenc->i_stride[1];
int off_y = 16 * i_mb_x + 16 * i_mb_y * stride_y; int off_y = 16 * i_mb_x + 16 * i_mb_y * stride_y;
int off_uv = 16 * i_mb_x + (16 * i_mb_y * stride_uv >> h->mb.chroma_v_shift); int off_uv = 16 * i_mb_x + (16 * i_mb_y * stride_uv >> CHROMA_V_SHIFT);
h->mc.prefetch_fenc( fenc->plane[0]+off_y, stride_y, h->mc.prefetch_fenc( fenc->plane[0]+off_y, stride_y,
fenc->plane[1]+off_uv, stride_uv, i_mb_x ); fenc->plane[1]+off_uv, stride_uv, i_mb_x );
} }
...@@ -556,7 +556,7 @@ NOINLINE void x264_copy_column8( pixel *dst, pixel *src ) ...@@ -556,7 +556,7 @@ NOINLINE void x264_copy_column8( pixel *dst, pixel *src )
static void ALWAYS_INLINE x264_macroblock_load_pic_pointers( x264_t *h, int mb_x, int mb_y, int i, int b_chroma, int b_mbaff ) static void ALWAYS_INLINE x264_macroblock_load_pic_pointers( x264_t *h, int mb_x, int mb_y, int i, int b_chroma, int b_mbaff )
{ {
int mb_interlaced = b_mbaff && MB_INTERLACED; int mb_interlaced = b_mbaff && MB_INTERLACED;
int height = b_chroma ? 16 >> h->mb.chroma_v_shift : 16; int height = b_chroma ? 16 >> CHROMA_V_SHIFT : 16;
int i_stride = h->fdec->i_stride[i]; int i_stride = h->fdec->i_stride[i];
int i_stride2 = i_stride << mb_interlaced; int i_stride2 = i_stride << mb_interlaced;
int i_pix_offset = mb_interlaced int i_pix_offset = mb_interlaced
...@@ -873,8 +873,8 @@ static void ALWAYS_INLINE x264_macroblock_cache_load( x264_t *h, int mb_x, int m ...@@ -873,8 +873,8 @@ static void ALWAYS_INLINE x264_macroblock_cache_load( x264_t *h, int mb_x, int m
/* load non_zero_count */ /* load non_zero_count */
CP32( &h->mb.cache.non_zero_count[x264_scan8[ 0] - 8], &nnz[top][12] ); CP32( &h->mb.cache.non_zero_count[x264_scan8[ 0] - 8], &nnz[top][12] );
CP32( &h->mb.cache.non_zero_count[x264_scan8[16] - 8], &nnz[top][16-4 + (16>>h->mb.chroma_v_shift)] ); CP32( &h->mb.cache.non_zero_count[x264_scan8[16] - 8], &nnz[top][16-4 + (16>>CHROMA_V_SHIFT)] );
CP32( &h->mb.cache.non_zero_count[x264_scan8[32] - 8], &nnz[top][32-4 + (16>>h->mb.chroma_v_shift)] ); CP32( &h->mb.cache.non_zero_count[x264_scan8[32] - 8], &nnz[top][32-4 + (16>>CHROMA_V_SHIFT)] );
/* Finish the prefetching */ /* Finish the prefetching */
for( int l = 0; l < lists; l++ ) for( int l = 0; l < lists; l++ )
...@@ -927,7 +927,7 @@ static void ALWAYS_INLINE x264_macroblock_cache_load( x264_t *h, int mb_x, int m ...@@ -927,7 +927,7 @@ static void ALWAYS_INLINE x264_macroblock_cache_load( x264_t *h, int mb_x, int m
if( CHROMA_FORMAT >= CHROMA_422 ) if( CHROMA_FORMAT >= CHROMA_422 )
{ {
int offset = (4>>h->mb.chroma_h_shift) - 4; int offset = (4>>CHROMA_H_SHIFT) - 4;
h->mb.cache.non_zero_count[x264_scan8[16+ 0] - 1] = nnz[ltop][left_index_table->nnz[0]+16+offset]; h->mb.cache.non_zero_count[x264_scan8[16+ 0] - 1] = nnz[ltop][left_index_table->nnz[0]+16+offset];
h->mb.cache.non_zero_count[x264_scan8[16+ 2] - 1] = nnz[ltop][left_index_table->nnz[1]+16+offset]; h->mb.cache.non_zero_count[x264_scan8[16+ 2] - 1] = nnz[ltop][left_index_table->nnz[1]+16+offset];
h->mb.cache.non_zero_count[x264_scan8[16+ 8] - 1] = nnz[lbot][left_index_table->nnz[2]+16+offset]; h->mb.cache.non_zero_count[x264_scan8[16+ 8] - 1] = nnz[lbot][left_index_table->nnz[2]+16+offset];
...@@ -1449,7 +1449,7 @@ void x264_macroblock_deblock_strength( x264_t *h ) ...@@ -1449,7 +1449,7 @@ void x264_macroblock_deblock_strength( x264_t *h )
/* Early termination: in this case, nnz guarantees all edges use strength 2.*/ /* Early termination: in this case, nnz guarantees all edges use strength 2.*/
if( h->mb.b_transform_8x8 && !CHROMA444 ) if( h->mb.b_transform_8x8 && !CHROMA444 )
{ {
int cbp_mask = 0xf >> h->mb.chroma_v_shift; int cbp_mask = 0xf >> CHROMA_V_SHIFT;
if( (h->mb.i_cbp_luma&cbp_mask) == cbp_mask ) if( (h->mb.i_cbp_luma&cbp_mask) == cbp_mask )
{ {
M32( bs[0][0] ) = 0x02020202; M32( bs[0][0] ) = 0x02020202;
...@@ -1620,7 +1620,7 @@ void x264_macroblock_deblock_strength( x264_t *h ) ...@@ -1620,7 +1620,7 @@ void x264_macroblock_deblock_strength( x264_t *h )
static void ALWAYS_INLINE x264_macroblock_store_pic( x264_t *h, int mb_x, int mb_y, int i, int b_chroma, int b_mbaff ) static void ALWAYS_INLINE x264_macroblock_store_pic( x264_t *h, int mb_x, int mb_y, int i, int b_chroma, int b_mbaff )
{ {
int height = b_chroma ? 16>>h->mb.chroma_v_shift : 16; int height = b_chroma ? 16>>CHROMA_V_SHIFT : 16;
int i_stride = h->fdec->i_stride[i]; int i_stride = h->fdec->i_stride[i];
int i_stride2 = i_stride << (b_mbaff && MB_INTERLACED); int i_stride2 = i_stride << (b_mbaff && MB_INTERLACED);
int i_pix_offset = (b_mbaff && MB_INTERLACED) int i_pix_offset = (b_mbaff && MB_INTERLACED)
...@@ -1647,7 +1647,7 @@ static void ALWAYS_INLINE x264_macroblock_backup_intra( x264_t *h, int mb_x, int ...@@ -1647,7 +1647,7 @@ static void ALWAYS_INLINE x264_macroblock_backup_intra( x264_t *h, int mb_x, int
} }
else else
{ {
int backup_src = (15>>h->mb.chroma_v_shift) * FDEC_STRIDE; int backup_src = (15>>CHROMA_V_SHIFT) * FDEC_STRIDE;
memcpy( &h->intra_border_backup[backup_dst][1][mb_x*16 ], h->mb.pic.p_fdec[1]+backup_src, 8*sizeof(pixel) ); memcpy( &h->intra_border_backup[backup_dst][1][mb_x*16 ], h->mb.pic.p_fdec[1]+backup_src, 8*sizeof(pixel) );
memcpy( &h->intra_border_backup[backup_dst][1][mb_x*16+8], h->mb.pic.p_fdec[2]+backup_src, 8*sizeof(pixel) ); memcpy( &h->intra_border_backup[backup_dst][1][mb_x*16+8], h->mb.pic.p_fdec[2]+backup_src, 8*sizeof(pixel) );
} }
...@@ -1677,8 +1677,8 @@ static void ALWAYS_INLINE x264_macroblock_backup_intra( x264_t *h, int mb_x, int ...@@ -1677,8 +1677,8 @@ static void ALWAYS_INLINE x264_macroblock_backup_intra( x264_t *h, int mb_x, int
/* In progressive we update intra_border_backup in-place, so the topleft neighbor will /* In progressive we update intra_border_backup in-place, so the topleft neighbor will
* no longer exist there when load_pic_pointers wants it. Move it within p_fdec instead. */ * no longer exist there when load_pic_pointers wants it. Move it within p_fdec instead. */
h->mb.pic.p_fdec[0][-FDEC_STRIDE-1] = h->mb.pic.p_fdec[0][-FDEC_STRIDE+15]; h->mb.pic.p_fdec[0][-FDEC_STRIDE-1] = h->mb.pic.p_fdec[0][-FDEC_STRIDE+15];
h->mb.pic.p_fdec[1][-FDEC_STRIDE-1] = h->mb.pic.p_fdec[1][-FDEC_STRIDE+(15>>h->mb.chroma_h_shift)]; h->mb.pic.p_fdec[1][-FDEC_STRIDE-1] = h->mb.pic.p_fdec[1][-FDEC_STRIDE+(15>>CHROMA_H_SHIFT)];
h->mb.pic.p_fdec[2][-FDEC_STRIDE-1] = h->mb.pic.p_fdec[2][-FDEC_STRIDE+(15>>h->mb.chroma_h_shift)]; h->mb.pic.p_fdec[2][-FDEC_STRIDE-1] = h->mb.pic.p_fdec[2][-FDEC_STRIDE+(15>>CHROMA_H_SHIFT)];
} }
} }
......
...@@ -85,7 +85,7 @@ int x264_cqm_init( x264_t *h ) ...@@ -85,7 +85,7 @@ int x264_cqm_init( x264_t *h )
int max_qp_err = -1; int max_qp_err = -1;
int max_chroma_qp_err = -1; int max_chroma_qp_err = -1;
int min_qp_err = QP_MAX+1; int min_qp_err = QP_MAX+1;
int num_8x8_lists = CHROMA444 ? 4 : 2; int num_8x8_lists = h->sps->i_chroma_format_idc == CHROMA_444 ? 4 : 2; /* Checkasm may segfault if optimized out by --chroma-format */
for( int i = 0; i < 4 + num_8x8_lists; i++ ) for( int i = 0; i < 4 + num_8x8_lists; i++ )
{ {
......
...@@ -30,6 +30,7 @@ Configuration options: ...@@ -30,6 +30,7 @@ Configuration options:
--disable-interlaced disable interlaced encoding support --disable-interlaced disable interlaced encoding support
--enable-visualize enable visualization (X11 only) --enable-visualize enable visualization (X11 only)
--bit-depth=BIT_DEPTH set output bit depth (8-10) [8] --bit-depth=BIT_DEPTH set output bit depth (8-10) [8]
--chroma-format=FORMAT output chroma format (420, 422, 444, all) [all]
Advanced options: Advanced options:
--disable-asm disable platform-specific assembly optimizations --disable-asm disable platform-specific assembly optimizations
...@@ -237,6 +238,7 @@ strip="no" ...@@ -237,6 +238,7 @@ strip="no"
pic="no" pic="no"
vis="no" vis="no"
bit_depth="8" bit_depth="8"
chroma_format="all"
compiler="GNU" compiler="GNU"
CFLAGS="$CFLAGS -Wall -I." CFLAGS="$CFLAGS -Wall -I."
...@@ -357,6 +359,13 @@ for opt do ...@@ -357,6 +359,13 @@ for opt do
fi fi
bit_depth=`expr $bit_depth + 0` bit_depth=`expr $bit_depth + 0`
;; ;;
--chroma-format=*)
chroma_format="$optarg"
if [ $chroma_format != "420" -a $chroma_format != "422" -a $chroma_format != "444" -a $chroma_format != "all" ]; then
echo "Supplied chroma format must be 420, 422, 444 or all."
exit 1
fi
;;
*) *)
echo "Unknown option $opt, ignored" echo "Unknown option $opt, ignored"
;; ;;
...@@ -912,6 +921,10 @@ if [ "$bit_depth" -gt "8" ]; then ...@@ -912,6 +921,10 @@ if [ "$bit_depth" -gt "8" ]; then
ASFLAGS="$ASFLAGS -DHIGH_BIT_DEPTH" ASFLAGS="$ASFLAGS -DHIGH_BIT_DEPTH"
fi fi
if [ "$chroma_format" != "all" ]; then
define CHROMA_FORMAT CHROMA_$chroma_format
fi
ASFLAGS="$ASFLAGS -DBIT_DEPTH=$bit_depth" ASFLAGS="$ASFLAGS -DBIT_DEPTH=$bit_depth"
[ $gpl = yes ] && define HAVE_GPL && x264_gpl=1 || x264_gpl=0 [ $gpl = yes ] && define HAVE_GPL && x264_gpl=1 || x264_gpl=0
...@@ -966,10 +979,13 @@ rm -f conftest* ...@@ -966,10 +979,13 @@ rm -f conftest*
# generate exported config file # generate exported config file
config_chroma_format="X264_CSP_I$chroma_format"
[ "$config_chroma_format" == "X264_CSP_Iall" ] && config_chroma_format="0"
cat > x264_config.h << EOF cat > x264_config.h << EOF
#define X264_BIT_DEPTH $bit_depth #define X264_BIT_DEPTH $bit_depth
#define X264_GPL $x264_gpl #define X264_GPL $x264_gpl
#define X264_INTERLACED $x264_interlaced #define X264_INTERLACED $x264_interlaced
#define X264_CHROMA_FORMAT $config_chroma_format
EOF EOF
# generate config files # generate config files
...@@ -1088,27 +1104,28 @@ gpl_filters="" ...@@ -1088,27 +1104,28 @@ gpl_filters=""
[ $gpl = yes ] && filters="$filters $gpl_filters" [ $gpl = yes ] && filters="$filters $gpl_filters"
cat > conftest.log <<EOF cat > conftest.log <<EOF
Platform: $ARCH platform: $ARCH
System: $SYS system: $SYS
cli: $cli cli: $cli
libx264: $cli_libx264 libx264: $cli_libx264
shared: $shared shared: $shared
static: $static static: $static
asm: $asm asm: $asm
interlaced: $interlaced interlaced: $interlaced
avs: $avs avs: $avs
lavf: $lavf lavf: $lavf
ffms: $ffms ffms: $ffms
gpac: $gpac gpac: $gpac
gpl: $gpl gpl: $gpl
thread: $thread thread: $thread
filters: $filters filters: $filters
debug: $debug debug: $debug
gprof: $gprof gprof: $gprof
strip: $strip strip: $strip
PIC: $pic PIC: $pic
visualize: $vis visualize: $vis
bit depth: $bit_depth bit depth: $bit_depth
chroma format: $chroma_format
EOF EOF
echo >> config.log echo >> config.log
......
...@@ -1287,8 +1287,8 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a ) ...@@ -1287,8 +1287,8 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
(m)->i_stride[1] = h->mb.pic.i_stride[1]; \ (m)->i_stride[1] = h->mb.pic.i_stride[1]; \
(m)->i_stride[2] = h->mb.pic.i_stride[2]; \ (m)->i_stride[2] = h->mb.pic.i_stride[2]; \
(m)->p_fenc[0] = &(src)[0][(xoff)+(yoff)*FENC_STRIDE]; \ (m)->p_fenc[0] = &(src)[0][(xoff)+(yoff)*FENC_STRIDE]; \
(m)->p_fenc[1] = &(src)[1][((xoff)>>h->mb.chroma_h_shift)+((yoff)>>h->mb.chroma_v_shift)*FENC_STRIDE]; \ (m)->p_fenc[1] = &(src)[1][((xoff)>>CHROMA_H_SHIFT)+((yoff)>>CHROMA_V_SHIFT)*FENC_STRIDE]; \
(m)->p_fenc[2] = &(src)[2][((xoff)>>h->mb.chroma_h_shift)+((yoff)>>h->mb.chroma_v_shift)*FENC_STRIDE]; \ (m)->p_fenc[2] = &(src)[2][((xoff)>>CHROMA_H_SHIFT)+((yoff)>>CHROMA_V_SHIFT)*FENC_STRIDE]; \
} }
#define LOAD_HPELS(m, src, list, ref, xoff, yoff) \ #define LOAD_HPELS(m, src, list, ref, xoff, yoff) \
...@@ -1309,7 +1309,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a ) ...@@ -1309,7 +1309,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
(m)->p_fref[11] = &(src)[11][(xoff)+(yoff)*(m)->i_stride[2]]; \ (m)->p_fref[11] = &(src)[11][(xoff)+(yoff)*(m)->i_stride[2]]; \
} \ } \
else \ else \
(m)->p_fref[4] = &(src)[4][(xoff)+((yoff)>>h->mb.chroma_v_shift)*(m)->i_stride[1]]; \ (m)->p_fref[4] = &(src)[4][(xoff)+((yoff)>>CHROMA_V_SHIFT)*(m)->i_stride[1]]; \
(m)->integral = &h->mb.pic.p_integral[list][ref][(xoff)+(yoff)*(m)->i_stride[0]]; \ (m)->integral = &h->mb.pic.p_integral[list][ref][(xoff)+(yoff)*(m)->i_stride[0]]; \
(m)->weight = x264_weight_none; \ (m)->weight = x264_weight_none; \
(m)->i_ref = ref; \ (m)->i_ref = ref; \
...@@ -1887,7 +1887,7 @@ static ALWAYS_INLINE int x264_analyse_bi_chroma( x264_t *h, x264_mb_analysis_t * ...@@ -1887,7 +1887,7 @@ static ALWAYS_INLINE int x264_analyse_bi_chroma( x264_t *h, x264_mb_analysis_t *
} \ } \
else \ else \
{ \ { \
int v_shift = h->mb.chroma_v_shift; \ int v_shift = CHROMA_V_SHIFT; \
int l0_mvy_offset = v_shift & MB_INTERLACED & m0.i_ref ? (h->mb.i_mb_y & 1)*4 - 2 : 0; \ int l0_mvy_offset = v_shift & MB_INTERLACED & m0.i_ref ? (h->mb.i_mb_y & 1)*4 - 2 : 0; \
int l1_mvy_offset = v_shift & MB_INTERLACED & m1.i_ref ? (h->mb.i_mb_y & 1)*4 - 2 : 0; \ int l1_mvy_offset = v_shift & MB_INTERLACED & m1.i_ref ? (h->mb.i_mb_y & 1)*4 - 2 : 0; \
h->mc.mc_chroma( pix[0], pix[1], 16, m0.p_fref[4], m0.i_stride[1], \ h->mc.mc_chroma( pix[0], pix[1], 16, m0.p_fref[4], m0.i_stride[1], \
...@@ -1934,8 +1934,8 @@ static void x264_mb_analyse_inter_direct( x264_t *h, x264_mb_analysis_t *a ) ...@@ -1934,8 +1934,8 @@ static void x264_mb_analyse_inter_direct( x264_t *h, x264_mb_analysis_t *a )
&p_fdec[x+y*FDEC_STRIDE], FDEC_STRIDE ); &p_fdec[x+y*FDEC_STRIDE], FDEC_STRIDE );
if( h->mb.b_chroma_me ) if( h->mb.b_chroma_me )
{ {
int fenc_offset = (x>>h->mb.chroma_h_shift) + (y>>h->mb.chroma_v_shift)*FENC_STRIDE; int fenc_offset = (x>>CHROMA_H_SHIFT) + (y>>CHROMA_V_SHIFT)*FENC_STRIDE;
int fdec_offset = (x>>h->mb.chroma_h_shift) + (y>>h->mb.chroma_v_shift)*FDEC_STRIDE; int fdec_offset = (x>>CHROMA_H_SHIFT) + (y>>CHROMA_V_SHIFT)*FDEC_STRIDE;
a->i_cost8x8direct[i] += h->pixf.mbcmp[chromapix]( &h->mb.pic.p_fenc[1][fenc_offset], FENC_STRIDE, a->i_cost8x8direct[i] += h->pixf.mbcmp[chromapix]( &h->mb.pic.p_fenc[1][fenc_offset], FENC_STRIDE,
&h->mb.pic.p_fdec[1][fdec_offset], FDEC_STRIDE ) &h->mb.pic.p_fdec[1][fdec_offset], FDEC_STRIDE )
+ h->pixf.mbcmp[chromapix]( &h->mb.pic.p_fenc[2][fenc_offset], FENC_STRIDE, + h->pixf.mbcmp[chromapix]( &h->mb.pic.p_fenc[2][fenc_offset], FENC_STRIDE,
...@@ -2097,7 +2097,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) ...@@ -2097,7 +2097,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
{ {
ALIGNED_ARRAY_16( pixel, pixuv, [2],[16*FENC_STRIDE] ); ALIGNED_ARRAY_16( pixel, pixuv, [2],[16*FENC_STRIDE] );
int chromapix = h->luma2chroma_pixel[PIXEL_16x16]; int chromapix = h->luma2chroma_pixel[PIXEL_16x16];
int v_shift = h->mb.chroma_v_shift; int v_shift = CHROMA_V_SHIFT;
if( v_shift & MB_INTERLACED & a->l0.bi16x16.i_ref ) if( v_shift & MB_INTERLACED & a->l0.bi16x16.i_ref )
{ {
...@@ -3251,7 +3251,7 @@ intra_analysis: ...@@ -3251,7 +3251,7 @@ intra_analysis:
h->mc.copy[PIXEL_16x16]( h->mb.pic.p_fenc[p], FENC_STRIDE, h->mb.pic.p_fdec[p], FDEC_STRIDE, 16 ); h->mc.copy[PIXEL_16x16]( h->mb.pic.p_fenc[p], FENC_STRIDE, h->mb.pic.p_fdec[p], FDEC_STRIDE, 16 );
if( !CHROMA444 ) if( !CHROMA444 )
{ {
int height = 16 >> h->mb.chroma_v_shift; int height = 16 >> CHROMA_V_SHIFT;
h->mc.copy[PIXEL_8x8] ( h->mb.pic.p_fenc[1], FENC_STRIDE, h->mb.pic.p_fdec[1], FDEC_STRIDE, height ); h->mc.copy[PIXEL_8x8] ( h->mb.pic.p_fenc[1], FENC_STRIDE, h->mb.pic.p_fdec[1], FDEC_STRIDE, height );
h->mc.copy[PIXEL_8x8] ( h->mb.pic.p_fenc[2], FENC_STRIDE, h->mb.pic.p_fdec[2], FDEC_STRIDE, height ); h->mc.copy[PIXEL_8x8] ( h->mb.pic.p_fenc[2], FENC_STRIDE, h->mb.pic.p_fdec[2], FDEC_STRIDE, height );
} }
......
...@@ -952,7 +952,7 @@ static ALWAYS_INLINE void x264_macroblock_write_cabac_internal( x264_t *h, x264_ ...@@ -952,7 +952,7 @@ static ALWAYS_INLINE void x264_macroblock_write_cabac_internal( x264_t *h, x264_
bs_write( &s, BIT_DEPTH, h->mb.pic.p_fenc[p][i] ); bs_write( &s, BIT_DEPTH, h->mb.pic.p_fenc[p][i] );
if( chroma ) if( chroma )
for( int ch = 1; ch < 3; ch++ ) for( int ch = 1; ch < 3; ch++ )
for( int i = 0; i < 16>>h->mb.chroma_v_shift; i++ ) for( int i = 0; i < 16>>CHROMA_V_SHIFT; i++ )
for( int j = 0; j < 8; j++ ) for( int j = 0; j < 8; j++ )
bs_write( &s, BIT_DEPTH, h->mb.pic.p_fenc[ch][i*FENC_STRIDE+j] ); bs_write( &s, BIT_DEPTH, h->mb.pic.p_fenc[ch][i*FENC_STRIDE+j] );
...@@ -1076,7 +1076,7 @@ if( (h->mb.i_neighbour & MB_TOP) && !h->mb.mb_transform_size[h->mb.i_mb_top_xy] ...@@ -1076,7 +1076,7 @@ if( (h->mb.i_neighbour & MB_TOP) && !h->mb.mb_transform_size[h->mb.i_mb_top_xy]
if( h->mb.i_cbp_chroma == 2 ) /* Chroma AC residual present */ if( h->mb.i_cbp_chroma == 2 ) /* Chroma AC residual present */
{ {
int step = 8 << h->mb.chroma_v_shift; int step = 8 << CHROMA_V_SHIFT;
for( int i = 16; i < 3*16; i += step ) for( int i = 16; i < 3*16; i += step )
for( int j = i; j < i+4; j++ ) for( int j = i; j < i+4; j++ )
x264_cabac_block_residual_cbf( h, cb, DCT_CHROMA_AC, j, h->dct.luma4x4[j]+1, b_intra ); x264_cabac_block_residual_cbf( h, cb, DCT_CHROMA_AC, j, h->dct.luma4x4[j]+1, b_intra );
...@@ -1231,7 +1231,7 @@ static void x264_chroma_size_cabac( x264_t *h, x264_cabac_t *cb ) ...@@ -1231,7 +1231,7 @@ static void x264_chroma_size_cabac( x264_t *h, x264_cabac_t *cb )
if( h->mb.i_cbp_chroma == 2 ) if( h->mb.i_cbp_chroma == 2 )
{ {
int step = 8 << h->mb.chroma_v_shift; int step = 8 << CHROMA_V_SHIFT;
for( int i = 16; i < 3*16; i += step ) for( int i = 16; i < 3*16; i += step )
for( int j = i; j < i+4; j++ ) for( int j = i; j < i+4; j++ )
x264_cabac_block_residual_cbf( h, cb, DCT_CHROMA_AC, j, h->dct.luma4x4[j]+1, 1 ); x264_cabac_block_residual_cbf( h, cb, DCT_CHROMA_AC, j, h->dct.luma4x4[j]+1, 1 );
......
...@@ -178,7 +178,7 @@ static int x264_cavlc_block_residual_internal( x264_t *h, int ctx_block_cat, dct ...@@ -178,7 +178,7 @@ static int x264_cavlc_block_residual_internal( x264_t *h, int ctx_block_cat, dct
if( ctx_block_cat == DCT_CHROMA_DC ) if( ctx_block_cat == DCT_CHROMA_DC )
{ {
if( i_total < 8>>h->mb.chroma_v_shift ) if( i_total < 8>>CHROMA_V_SHIFT )
{ {
vlc_t total_zeros = CHROMA_FORMAT == CHROMA_420 ? x264_total_zeros_2x2_dc[i_total-1][i_total_zero] vlc_t total_zeros = CHROMA_FORMAT == CHROMA_420 ? x264_total_zeros_2x2_dc[i_total-1][i_total_zero]
: x264_total_zeros_2x4_dc[i_total-1][i_total_zero]; : x264_total_zeros_2x4_dc[i_total-1][i_total_zero];
...@@ -202,7 +202,7 @@ static const uint8_t ct_index[17] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3}; ...@@ -202,7 +202,7 @@ static const uint8_t ct_index[17] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3};
#define x264_cavlc_block_residual(h,cat,idx,l)\ #define x264_cavlc_block_residual(h,cat,idx,l)\
{\ {\
int nC = cat == DCT_CHROMA_DC ? 3 + CHROMA_FORMAT\ int nC = cat == DCT_CHROMA_DC ? 5 - CHROMA_V_SHIFT\
: ct_index[x264_mb_predict_non_zero_code( h, cat == DCT_LUMA_DC ? (idx - LUMA_DC)*16 : idx )];\ : ct_index[x264_mb_predict_non_zero_code( h, cat == DCT_LUMA_DC ? (idx - LUMA_DC)*16 : idx )];\
uint8_t *nnz = &h->mb.cache.non_zero_count[x264_scan8[idx]];\ uint8_t *nnz = &h->mb.cache.non_zero_count[x264_scan8[idx]];\
if( !*nnz )\ if( !*nnz )\
...@@ -505,7 +505,7 @@ void x264_macroblock_write_cavlc( x264_t *h ) ...@@ -505,7 +505,7 @@ void x264_macroblock_write_cavlc( x264_t *h )
bs_write( s, BIT_DEPTH, h->mb.pic.p_fenc[p][i] ); bs_write( s, BIT_DEPTH, h->mb.pic.p_fenc[p][i] );
if( chroma ) if( chroma )
for( int ch = 1; ch < 3; ch++ ) for( int ch = 1; ch < 3; ch++ )
for( int i = 0; i < 16>>h->mb.chroma_v_shift; i++ ) for( int i = 0; i < 16>>CHROMA_V_SHIFT; i++ )
for( int j = 0; j < 8; j++ ) for( int j = 0; j < 8; j++ )
bs_write( s, BIT_DEPTH, h->mb.pic.p_fenc[ch][i*FENC_STRIDE+j] ); bs_write( s, BIT_DEPTH, h->mb.pic.p_fenc[ch][i*FENC_STRIDE+j] );
...@@ -564,7 +564,7 @@ void x264_macroblock_write_cavlc( x264_t *h ) ...@@ -564,7 +564,7 @@ void x264_macroblock_write_cavlc( x264_t *h )
x264_cavlc_block_residual( h, DCT_CHROMA_DC, CHROMA_DC+1, h->dct.chroma_dc[1] ); x264_cavlc_block_residual( h, DCT_CHROMA_DC, CHROMA_DC+1, h->dct.chroma_dc[1] );
if( h->mb.i_cbp_chroma == 2 ) /* Chroma AC residual present */ if( h->mb.i_cbp_chroma == 2 ) /* Chroma AC residual present */
{ {
int step = 8 << h->mb.chroma_v_shift; int step = 8 << CHROMA_V_SHIFT;
for( int i = 16; i < 3*16; i += step ) for( int i = 16; i < 3*16; i += step )
for( int j = i; j < i+4; j++ ) for( int j = i; j < i+4; j++ )
x264_cavlc_block_residual( h, DCT_CHROMA_AC, j, h->dct.luma4x4[j]+1 ); x264_cavlc_block_residual( h, DCT_CHROMA_AC, j, h->dct.luma4x4[j]+1 );
...@@ -691,7 +691,7 @@ static int x264_chroma_size_cavlc( x264_t *h ) ...@@ -691,7 +691,7 @@ static int x264_chroma_size_cavlc( x264_t *h )
if( h->mb.i_cbp_chroma == 2 ) if( h->mb.i_cbp_chroma == 2 )
{ {
int step = 8 << h->mb.chroma_v_shift; int step = 8 << CHROMA_V_SHIFT;
for( int i = 16; i < 3*16; i += step ) for( int i = 16; i < 3*16; i += step )
for( int j = i; j < i+4; j++ ) for( int j = i; j < i+4; j++ )
x264_cavlc_block_residual( h, DCT_CHROMA_AC, j, h->dct.luma4x4[j]+1 ); x264_cavlc_block_residual( h, DCT_CHROMA_AC, j, h->dct.luma4x4[j]+1 );
......
...@@ -79,7 +79,7 @@ static void x264_frame_dump( x264_t *h ) ...@@ -79,7 +79,7 @@ static void x264_frame_dump( x264_t *h )
if( !CHROMA444 ) if( !CHROMA444 )
{ {
int cw = h->param.i_width>>1; int cw = h->param.i_width>>1;
int ch = h->param.i_height>>h->mb.chroma_v_shift; int ch = h->param.i_height>>CHROMA_V_SHIFT;
pixel *planeu = x264_malloc( (cw*ch*2+32)*sizeof(pixel) ); pixel *planeu = x264_malloc( (cw*ch*2+32)*sizeof(pixel) );
pixel *planev = planeu + cw*ch + 16; pixel *planev = planeu + cw*ch + 16;
h->mc.plane_copy_deinterleave( planeu, cw, planev, cw, h->fdec->plane[1], h->fdec->i_stride[1], cw, ch ); h->mc.plane_copy_deinterleave( planeu, cw, planev, cw, h->fdec->plane[1], h->fdec->i_stride[1], cw, ch );
...@@ -418,6 +418,23 @@ static int x264_validate_parameters( x264_t *h, int b_open ) ...@@ -418,6 +418,23 @@ static int x264_validate_parameters( x264_t *h, int b_open )
} }
int i_csp = h->param.i_csp & X264_CSP_MASK; int i_csp = h->param.i_csp & X264_CSP_MASK;
#if X264_CHROMA_FORMAT
if( CHROMA_FORMAT != CHROMA_420 && i_csp >= X264_CSP_I420 && i_csp <= X264_CSP_NV12 )
{
x264_log( h, X264_LOG_ERROR, "not compiled with 4:2:0 support\n" );
return -1;
}
else if( CHROMA_FORMAT != CHROMA_422 && i_csp >= X264_CSP_I422 && i_csp <= X264_CSP_NV16 )
{
x264_log( h, X264_LOG_ERROR, "not compiled with 4:2:2 support\n" );
return -1;
}
else if( CHROMA_FORMAT != CHROMA_444 && i_csp >= X264_CSP_I444 && i_csp <= X264_CSP_RGB )
{
x264_log( h, X264_LOG_ERROR, "not compiled with 4:4:4 support\n" );
return -1;
}
#endif
if( i_csp <= X264_CSP_NONE || i_csp >= X264_CSP_MAX ) if( i_csp <= X264_CSP_NONE || i_csp >= X264_CSP_MAX )
{ {
x264_log( h, X264_LOG_ERROR, "invalid CSP (only I420/YV12/NV12/I422/YV16/NV16/I444/YV24/BGR/BGRA/RGB supported)\n" );