Gives a slight speed increase and significant binary size reduction when only one chroma format is needed.
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 );
/****************************************************************************
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;
#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 {\
# 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.
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 )
}
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;
}
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 );
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;
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 )
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;
{
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;
}
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;
}
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;
}
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 )
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 );
}
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
/* 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++ )
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];
/* 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;
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)
}
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) );
}
/* 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)];
}
}
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++ )
{
--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
pic="no"
vis="no"
bit_depth="8"
+chroma_format="all"
compiler="GNU"
CFLAGS="$CFLAGS -Wall -I."
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"
;;
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
# 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_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
[ $gpl = yes ] && filters="$filters $gpl_filters"
cat > conftest.log <<EOF
-Platform: $ARCH
-System: $SYS
-cli: $cli
-libx264: $cli_libx264
-shared: $shared
-static: $static
-asm: $asm
-interlaced: $interlaced
-avs: $avs
-lavf: $lavf
-ffms: $ffms
-gpac: $gpac
-gpl: $gpl
-thread: $thread
-filters: $filters
-debug: $debug
-gprof: $gprof
-strip: $strip
-PIC: $pic
-visualize: $vis
-bit depth: $bit_depth
+platform: $ARCH
+system: $SYS
+cli: $cli
+libx264: $cli_libx264
+shared: $shared
+static: $static
+asm: $asm
+interlaced: $interlaced
+avs: $avs
+lavf: $lavf
+ffms: $ffms
+gpac: $gpac
+gpl: $gpl
+thread: $thread
+filters: $filters
+debug: $debug
+gprof: $gprof
+strip: $strip
+PIC: $pic
+visualize: $vis
+bit depth: $bit_depth
+chroma format: $chroma_format
EOF
echo >> config.log
(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) \
(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; \
} \
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], \
&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,
{
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 )
{
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 );
}
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] );
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 );
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 );
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];
#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 )\
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] );
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 );
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 );
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 );
}
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" );
* 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) );
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],
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 );
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 );
}
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. */
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
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];
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;
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
{
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 )
{
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);
}
}
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 )
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
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 );
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;
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 )
{
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
{
#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" );
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"
" - 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" );
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:
#include "x264_config.h"
-#define X264_BUILD 118
+#define X264_BUILD 119
/* x264_t:
* opaque handler for encoder */
* colorspace depth as well. */
extern const int x264_bit_depth;
+/* x264_chroma_format:
+ * Specifies the chroma formats that x264 supports encoding. When this
+ * value is non-zero, then it represents a X264_CSP_* that is the only
+ * chroma format that x264 supports encoding. If the value is 0 then
+ * there are no restrictions. */
+extern const int x264_chroma_format;
+
enum pic_struct_e
{
PIC_STRUCT_AUTO = 0, // automatically decide (default)