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 @@
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 );
/****************************************************************************
......@@ -52,7 +54,7 @@ void x264_param_default( x264_param_t *param )
param->i_sync_lookahead = X264_SYNC_LOOKAHEAD_AUTO;
/* 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_height = 0;
param->vui.i_sar_width = 0;
......
......@@ -40,9 +40,6 @@
#define IS_DISPOSABLE(type) ( type == X264_TYPE_B )
#define FIX8(f) ((int)(f*(1<<8)+.5))
#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 )\
do {\
......@@ -105,6 +102,17 @@ do {\
# define PARAM_INTERLACED 0
#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)
/* Unions for type-punning.
......
......@@ -394,7 +394,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
int stridey = h->fdec->i_stride[0];
int strideuv = h->fdec->i_stride[1];
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;
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 )
}
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]];
luma_qp[1] = (qp + 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 )
}
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 );
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 );
......@@ -486,8 +486,8 @@ void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_e
return;
for( int i = 0; i < frame->i_plane; i++ )
{
int h_shift = i && h->mb.chroma_h_shift;
int v_shift = i && h->mb.chroma_v_shift;
int h_shift = i && CHROMA_H_SHIFT;
int v_shift = i && CHROMA_V_SHIFT;
int stride = frame->i_stride[i];
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;
......@@ -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 )
{
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,
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 )
......@@ -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++ )
{
int i_width = h->param.i_width;
int h_shift = i && h->mb.chroma_h_shift;
int v_shift = i && h->mb.chroma_v_shift;
int h_shift = i && CHROMA_H_SHIFT;
int v_shift = i && CHROMA_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_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 )
{
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 height = 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
}
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
if( v_shift & MB_INTERLACED & i_ref )
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
}
else
{
int v_shift = h->mb.chroma_v_shift;
int v_shift = CHROMA_V_SHIFT;
if( v_shift & MB_INTERLACED & i_ref )
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
}
else
{
int v_shift = h->mb.chroma_v_shift;
int v_shift = CHROMA_V_SHIFT;
if( v_shift & MB_INTERLACED & i_ref0 )
mvy0 += (h->mb.i_mb_y & 1)*4 - 2;
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 )
int stride_y = fenc->i_stride[0];
int stride_uv = fenc->i_stride[1];
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,
fenc->plane[1]+off_uv, stride_uv, i_mb_x );
}
......@@ -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 )
{
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_stride2 = i_stride << 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
/* 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[16] - 8], &nnz[top][16-4 + (16>>h->mb.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[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>>CHROMA_V_SHIFT)] );
/* Finish the prefetching */
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
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+ 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];
......@@ -1449,7 +1449,7 @@ void x264_macroblock_deblock_strength( x264_t *h )
/* Early termination: in this case, nnz guarantees all edges use strength 2.*/
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 )
{
M32( bs[0][0] ) = 0x02020202;
......@@ -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 )
{
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_stride2 = i_stride << (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
}
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+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
/* 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. */
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[2][-FDEC_STRIDE-1] = h->mb.pic.p_fdec[2][-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>>CHROMA_H_SHIFT)];
}
}
......
......@@ -85,7 +85,7 @@ int x264_cqm_init( x264_t *h )
int max_qp_err = -1;
int max_chroma_qp_err = -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++ )
{
......
......@@ -30,6 +30,7 @@ Configuration options:
--disable-interlaced disable interlaced encoding support
--enable-visualize enable visualization (X11 only)
--bit-depth=BIT_DEPTH set output bit depth (8-10) [8]
--chroma-format=FORMAT output chroma format (420, 422, 444, all) [all]
Advanced options:
--disable-asm disable platform-specific assembly optimizations
......@@ -237,6 +238,7 @@ strip="no"
pic="no"
vis="no"
bit_depth="8"
chroma_format="all"
compiler="GNU"
CFLAGS="$CFLAGS -Wall -I."
......@@ -357,6 +359,13 @@ for opt do
fi
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"
;;
......@@ -912,6 +921,10 @@ if [ "$bit_depth" -gt "8" ]; then
ASFLAGS="$ASFLAGS -DHIGH_BIT_DEPTH"
fi
if [ "$chroma_format" != "all" ]; then
define CHROMA_FORMAT CHROMA_$chroma_format
fi
ASFLAGS="$ASFLAGS -DBIT_DEPTH=$bit_depth"
[ $gpl = yes ] && define HAVE_GPL && x264_gpl=1 || x264_gpl=0
......@@ -966,10 +979,13 @@ rm -f conftest*
# 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
#define X264_BIT_DEPTH $bit_depth
#define X264_GPL $x264_gpl
#define X264_INTERLACED $x264_interlaced
#define X264_CHROMA_FORMAT $config_chroma_format
EOF
# generate config files
......@@ -1088,8 +1104,8 @@ gpl_filters=""
[ $gpl = yes ] && filters="$filters $gpl_filters"
cat > conftest.log <<EOF
Platform: $ARCH
System: $SYS
platform: $ARCH
system: $SYS
cli: $cli
libx264: $cli_libx264
shared: $shared
......@@ -1109,6 +1125,7 @@ strip: $strip
PIC: $pic
visualize: $vis
bit depth: $bit_depth
chroma format: $chroma_format
EOF
echo >> config.log
......
......@@ -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[2] = h->mb.pic.i_stride[2]; \
(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[2] = &(src)[2][((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)>>CHROMA_H_SHIFT)+((yoff)>>CHROMA_V_SHIFT)*FENC_STRIDE]; \
}
#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 )
(m)->p_fref[11] = &(src)[11][(xoff)+(yoff)*(m)->i_stride[2]]; \
} \
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)->weight = x264_weight_none; \
(m)->i_ref = ref; \
......@@ -1887,7 +1887,7 @@ static ALWAYS_INLINE int x264_analyse_bi_chroma( x264_t *h, x264_mb_analysis_t *
} \
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 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], \
......@@ -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 );
if( h->mb.b_chroma_me )
{
int fenc_offset = (x>>h->mb.chroma_h_shift) + (y>>h->mb.chroma_v_shift)*FENC_STRIDE;
int fdec_offset = (x>>h->mb.chroma_h_shift) + (y>>h->mb.chroma_v_shift)*FDEC_STRIDE;
int fenc_offset = (x>>CHROMA_H_SHIFT) + (y>>CHROMA_V_SHIFT)*FENC_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,
&h->mb.pic.p_fdec[1][fdec_offset], FDEC_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 )
{
ALIGNED_ARRAY_16( pixel, pixuv, [2],[16*FENC_STRIDE] );
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 )
{
......@@ -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 );
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[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_
bs_write( &s, BIT_DEPTH, h->mb.pic.p_fenc[p][i] );
if( chroma )
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++ )
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]
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 j = i; j < i+4; j++ )
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 )
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 j = i; j < i+4; j++ )
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
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]
: 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};
#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 )];\
uint8_t *nnz = &h->mb.cache.non_zero_count[x264_scan8[idx]];\
if( !*nnz )\
......@@ -505,7 +505,7 @@ void x264_macroblock_write_cavlc( x264_t *h )
bs_write( s, BIT_DEPTH, h->mb.pic.p_fenc[p][i] );
if( chroma )
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++ )
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 )
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 */
{
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 j = i; j < i+4; j++ )
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 )
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 j = i; j < i+4; j++ )
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 )
if( !CHROMA444 )
{
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 *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 );
......@@ -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;
#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 )
{
x264_log( h, X264_LOG_ERROR, "invalid CSP (only I420/YV12/NV12/I422/YV16/NV16/I444/YV24/BGR/BGRA/RGB supported)\n" );
......@@ -1832,7 +1849,7 @@ static void x264_fdec_filter_row( x264_t *h, int mb_y, int b_inloop )
* consistency by copying deblocked pixels between planes. */
if( PARAM_INTERLACED )
for( int p = 0; p < h->fdec->i_plane; p++ )
for( int i = minpix_y>>(h->mb.chroma_v_shift && p); i < maxpix_y>>(h->mb.chroma_v_shift && p); i++ )
for( int i = minpix_y>>(CHROMA_V_SHIFT && p); i < maxpix_y>>(CHROMA_V_SHIFT && p); i++ )
memcpy( h->fdec->plane_fld[p] + i*h->fdec->i_stride[p],
h->fdec->plane[p] + i*h->fdec->i_stride[p],
h->mb.i_mb_width*16*sizeof(pixel) );
......@@ -1871,7 +1888,7 @@ static void x264_fdec_filter_row( x264_t *h, int mb_y, int b_inloop )
if( !CHROMA444 )
{
uint64_t ssd_u, ssd_v;
int v_shift = h->mb.chroma_v_shift;
int v_shift = CHROMA_V_SHIFT;
x264_pixel_ssd_nv12( &h->pixf,
h->fdec->plane[1] + (minpix_y>>v_shift) * h->fdec->i_stride[1], h->fdec->i_stride[1],
h->fenc->plane[1] + (minpix_y>>v_shift) * h->fenc->i_stride[1], h->fenc->i_stride[1],
......
......@@ -602,7 +602,7 @@ static void x264_macroblock_encode_skip( x264_t *h )
void x264_predict_lossless_chroma( x264_t *h, int i_mode )
{
int height = 16 >> h->mb.chroma_v_shift;
int height = 16 >> CHROMA_V_SHIFT;
if( i_mode == I_PRED_CHROMA_V )
{
h->mc.copy[PIXEL_8x8]( h->mb.pic.p_fdec[1], FDEC_STRIDE, h->mb.pic.p_fenc[1]-FENC_STRIDE, FENC_STRIDE, height );
......@@ -686,7 +686,7 @@ static ALWAYS_INLINE void x264_macroblock_encode_internal( x264_t *h, int plane_
h->mc.copy[PIXEL_16x16]( h->mb.pic.p_fdec[p], FDEC_STRIDE, h->mb.pic.p_fenc[p], FENC_STRIDE, 16 );
if( chroma )
{
int height = 16 >> h->mb.chroma_v_shift;
int height = 16 >> CHROMA_V_SHIFT;
h->mc.copy[PIXEL_8x8] ( h->mb.pic.p_fdec[1], FDEC_STRIDE, h->mb.pic.p_fenc[1], FENC_STRIDE, height );
h->mc.copy[PIXEL_8x8] ( h->mb.pic.p_fdec[2], FDEC_STRIDE, h->mb.pic.p_fenc[2], FENC_STRIDE, height );
}
......@@ -722,7 +722,7 @@ static ALWAYS_INLINE void x264_macroblock_encode_internal( x264_t *h, int plane_
if( chroma )
{
int v_shift = h->mb.chroma_v_shift;
int v_shift = CHROMA_V_SHIFT;
int height = 16 >> v_shift;
/* Special case for mv0, which is (of course) very common in P-skip mode. */
......
......@@ -830,7 +830,7 @@ static void refine_subpel( x264_t *h, x264_me_t *m, int hpel_iters, int qpel_ite
const int i_pixel = m->i_pixel;
const int b_chroma_me = h->mb.b_chroma_me && (i_pixel <= PIXEL_8x8 || CHROMA444);
int chromapix = h->luma2chroma_pixel[i_pixel];
int chroma_v_shift = h->mb.chroma_v_shift;
int chroma_v_shift = CHROMA_V_SHIFT;
int mvy_offset = chroma_v_shift & MB_INTERLACED & m->i_ref ? (h->mb.i_mb_y & 1)*4 - 2 : 0;
ALIGNED_ARRAY_16( pixel, pix,[64*18] ); // really 17x17x2, but round up for alignment
......@@ -978,8 +978,8 @@ static void ALWAYS_INLINE x264_me_refine_bidir( x264_t *h, x264_me_t *m0, x264_m
ALIGNED_ARRAY_16( pixel, pixv_buf,[2],[9][16*16] );
pixel *src[3][2][9];
int chromapix = h->luma2chroma_pixel[i_pixel];
int chroma_v_shift = h->mb.chroma_v_shift;
int chroma_x = (8 >> h->mb.chroma_h_shift) * x;
int chroma_v_shift = CHROMA_V_SHIFT;
int chroma_x = (8 >> CHROMA_H_SHIFT) * x;
int chroma_y = (8 >> chroma_v_shift) * y;
pixel *pix = &h->mb.pic.p_fdec[0][8*x + 8*y*FDEC_STRIDE];
pixel *pixu = &h->mb.pic.p_fdec[1][chroma_x + chroma_y*FDEC_STRIDE];
......@@ -1176,7 +1176,7 @@ void x264_me_refine_qpel_rd( x264_t *h, x264_me_t *m, int i_lambda2, int i4, int
const int bw = x264_pixel_size[m->i_pixel].w;
const int bh = x264_pixel_size[m->i_pixel].h;
const int i_pixel = m->i_pixel;
int chroma_v_shift = h->mb.chroma_v_shift;
int chroma_v_shift = CHROMA_V_SHIFT;
int mvy_offset = chroma_v_shift & MB_INTERLACED & m->i_ref ? (h->mb.i_mb_y & 1)*4 - 2 : 0;
uint64_t bcost = COST_MAX64;
......
......@@ -219,7 +219,7 @@ static ALWAYS_INLINE uint32_t ac_energy_var( uint64_t sum_ssd, int shift, x264_f
static ALWAYS_INLINE uint32_t ac_energy_plane( x264_t *h, int mb_x, int mb_y, x264_frame_t *frame, int i, int b_chroma, int b_field, int b_store )
{
int height = b_chroma ? 16>>h->mb.chroma_v_shift : 16;
int height = b_chroma ? 16>>CHROMA_V_SHIFT : 16;
int stride = frame->i_stride[i];
int offset = b_field
? 16 * mb_x + height * (mb_y&~1) * stride + (mb_y&1) * stride
......@@ -229,7 +229,7 @@ static ALWAYS_INLINE uint32_t ac_energy_plane( x264_t *h, int mb_x, int mb_y, x2
{
ALIGNED_ARRAY_16( pixel, pix,[FENC_STRIDE*16] );
int chromapix = h->luma2chroma_pixel[PIXEL_16x16];
int shift = 7 - h->mb.chroma_v_shift;
int shift = 7 - CHROMA_V_SHIFT;
h->mc.load_deinterleave_chroma_fenc( pix, frame->plane[1] + offset, stride, height );
return ac_energy_var( h->pixf.var[chromapix]( pix, FENC_STRIDE ), shift, frame, 1, b_store )
......@@ -382,8 +382,8 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame, float *quant_off
{
uint64_t ssd = frame->i_pixel_ssd[i];
uint64_t sum = frame->i_pixel_sum[i];
int width = 16*h->mb.i_mb_width >> (i && h->mb.chroma_h_shift);
int height = 16*h->mb.i_mb_height >> (i && h->mb.chroma_v_shift);
int width = 16*h->mb.i_mb_width >> (i && CHROMA_H_SHIFT);
int height = 16*h->mb.i_mb_height >> (i && CHROMA_V_SHIFT);
frame->i_pixel_ssd[i] = ssd - (sum * sum + width * height / 2) / (width * height);
}
}
......
......@@ -249,8 +249,8 @@ uint64_t x264_rd_cost_part( x264_t *h, int i_lambda2, int i4, int i_pixel )
int ssd_y = 8*(i8>>1);
i_ssd = ssd_plane( h, i_pixel, 0, ssd_x, ssd_y );
int chromapix = h->luma2chroma_pixel[i_pixel];
int chromassd = ssd_plane( h, chromapix, 1, ssd_x>>h->mb.chroma_h_shift, ssd_y>>h->mb.chroma_v_shift )
+ ssd_plane( h, chromapix, 2, ssd_x>>h->mb.chroma_h_shift, ssd_y>>h->mb.chroma_v_shift );
int chromassd = ssd_plane( h, chromapix, 1, ssd_x>>CHROMA_H_SHIFT, ssd_y>>CHROMA_V_SHIFT )
+ ssd_plane( h, chromapix, 2, ssd_x>>CHROMA_H_SHIFT, ssd_y>>CHROMA_V_SHIFT );
i_ssd += ((uint64_t)chromassd * h->mb.i_chroma_lambda2_offset + 128) >> 8;
if( h->param.b_cabac )
......
......@@ -278,7 +278,7 @@ void x264_sps_write( bs_t *s, x264_sps_t *sps )
if( sps->i_profile_idc >= PROFILE_HIGH )
{
bs_write_ue( s, sps->i_chroma_format_idc );
if( sps->i_chroma_format_idc == 3 )
if( sps->i_chroma_format_idc == CHROMA_444 )
bs_write1( s, 0 ); // separate_colour_plane_flag
bs_write_ue( s, BIT_DEPTH-8 ); // bit_depth_luma_minus8
bs_write_ue( s, BIT_DEPTH-8 ); // bit_depth_chroma_minus8
......@@ -515,7 +515,7 @@ void x264_pps_write( bs_t *s, x264_sps_t *sps, x264_pps_t *pps )
bs_write1( s, 0 ); // Cr = Cb
if( pps->b_transform_8x8_mode )
{
if( sps->i_chroma_format_idc == 3 )
if( sps->i_chroma_format_idc == CHROMA_444 )
{
scaling_list_write( s, pps, CQM_8IY+4 );
scaling_list_write( s, pps, CQM_8IC+4 );
......
......@@ -109,7 +109,7 @@ static NOINLINE void x264_weight_cost_init_chroma( x264_t *h, x264_frame_t *fenc
int i_offset = i_stride / 2;
int i_lines = fenc->i_lines[1];
int i_width = fenc->i_width[1];
int v_shift = h->mb.chroma_v_shift;
int v_shift = CHROMA_V_SHIFT;
int cw = 8*h->mb.i_mb_width;
int ch = 16*h->mb.i_mb_height >> v_shift;
int height = 16 >> v_shift;
......@@ -227,7 +227,7 @@ static NOINLINE unsigned int x264_weight_cost_chroma( x264_t *h, x264_frame_t *f
ALIGNED_ARRAY_16( pixel, buf, [8*16] );
int pixoff = 0;
int chromapix = h->luma2chroma_pixel[PIXEL_16x16];
int height = 16 >> h->mb.chroma_v_shift;
int height = 16 >> CHROMA_V_SHIFT;
ALIGNED_16( static pixel flat[8] ) = {0};
if( w )
{
......
......@@ -121,7 +121,19 @@ static const char * const muxer_names[] =
static const char * const pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 };
static const char * const log_level_names[] = { "none", "error", "warning", "info", "debug", 0 };
static const char * const output_csp_names[] = { "i420", "i422", "i444", "rgb", 0 };
static const char * const output_csp_names[] =
{
#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420
"i420",
#endif
#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I422
"i422",
#endif
#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I444
"i444", "rgb",
#endif
0
};
typedef struct
{
......@@ -234,7 +246,7 @@ static void print_version_info()
#else
printf( "using an unknown compiler\n" );
#endif
printf( "configuration: --bit-depth=%d\n", x264_bit_depth );
printf( "configuration: --bit-depth=%d --chroma-format=%s\n", x264_bit_depth, X264_CHROMA_FORMAT ? (output_csp_names[0]+1) : "all" );
printf( "x264 license: " );
#if HAVE_GPL
printf( "GPL version 2 or later\n" );
......@@ -426,6 +438,7 @@ static void help( x264_param_t *defaults, int longhelp )
H0( " --profile <string> Force the limits of an H.264 profile\n"
" Overrides all settings.\n" );
H2(
#if X264_CHROMA_FORMAT <= X264_CSP_I420
#if BIT_DEPTH==8
" - baseline:\n"
" --no-8x8dct --bframes 0 --no-cabac\n"
......@@ -441,19 +454,28 @@ static void help( x264_param_t *defaults, int longhelp )
" - high10:\n"
" No lossless.\n"
" Support for bit depth 8-10.\n"
#endif
#if X264_CHROMA_FORMAT <= X264_CSP_I422
" - high422:\n"
" No lossless.\n"
" Support for bit depth 8-10.\n"
" Support for 4:2:0/4:2:2 chroma subsampling.\n"
#endif
" - high444:\n"
" Support for bit depth 8-10.\n"
" Support for 4:2:0/4:2:2/4:4:4 chroma subsampling.\n" );
else H0(
" - "
#if X264_CHROMA_FORMAT <= X264_CSP_I420
#if BIT_DEPTH==8
" - baseline,main,high,high10,high422,high444\n"
#else
" - high10,high422,high444\n"
"baseline,main,high,"
#endif
"high10,"
#endif
#if X264_CHROMA_FORMAT <= X264_CSP_I422
"high422,"
#endif
"high444\n"
);
H0( " --preset <string> Use a preset to select encoding settings [medium]\n"
" Overridden by user settings.\n" );
......@@ -1373,7 +1395,11 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
case OPT_OUTPUT_CSP:
FAIL_IF_ERROR( parse_enum_value( optarg, output_csp_names, &output_csp ), "Unknown output csp `%s'\n", optarg )
// correct the parsed value to the libx264 csp value
#if X264_CHROMA_FORMAT
static const uint8_t output_csp_fix[] = { X264_CHROMA_FORMAT, X264_CSP_RGB };
#else
static const uint8_t output_csp_fix[] = { X264_CSP_I420, X264_CSP_I422, X264_CSP_I444, X264_CSP_RGB };
#endif
param->i_csp = output_csp = output_csp_fix[output_csp];
break;
default:
......
......@@ -41,7 +41,7 @@
#include "x264_config.h"
#define X264_BUILD 118
#define X264_BUILD 119
/* x264_t:
* opaque handler for encoder */
......@@ -607,6 +607,13 @@ int x264_param_apply_profile( x264_param_t *, const char *profile );
* colorspace depth as well. */
extern const int x264_bit_depth;
/* x264_chroma_format:
* Specifies the chroma formats that x264 supports encoding. When this