x264_log_internal( X264_LOG_ERROR, "%s profile doesn't support a bit depth of %d\n", profile, param->i_bitdepth );
return -1;
}
+ if( p < PROFILE_HIGH && (param->i_csp & X264_CSP_MASK) == X264_CSP_I400 )
+ {
+ x264_log_internal( X264_LOG_ERROR, "%s profile doesn't support 4:0:0\n", profile );
+ return -1;
+ }
if( p == PROFILE_BASELINE )
{
# define CHROMA_V_SHIFT h->mb.chroma_v_shift
#endif
-#define CHROMA_SIZE(s) ((s)>>(CHROMA_H_SHIFT+CHROMA_V_SHIFT))
+#define CHROMA_SIZE(s) (CHROMA_FORMAT ? (s)>>(CHROMA_H_SHIFT+CHROMA_V_SHIFT) : 0)
#define FRAME_SIZE(s) ((s)+2*CHROMA_SIZE(s))
#define CHROMA444 (CHROMA_FORMAT == CHROMA_444)
int qp_thresh = 15 - X264_MIN( a, b ) - X264_MAX( 0, h->pps->i_chroma_qp_index_offset );
int stridey = h->fdec->i_stride[0];
int strideuv = h->fdec->i_stride[1];
+ int chroma_format = CHROMA_FORMAT;
int chroma444 = CHROMA444;
int chroma_height = 16 >> CHROMA_V_SHIFT;
intptr_t uvdiff = chroma444 ? h->fdec->plane[2] - h->fdec->plane[1] : 1;
deblock_edge##intra( h, pixy + 4*edge*(dir?stride2y:1),\
stride2y, bs[dir][edge], qp, a, b, 0,\
h->loopf.deblock_luma##intra[dir] );\
- if( CHROMA_FORMAT == CHROMA_444 )\
+ if( chroma_format == CHROMA_444 )\
{\
deblock_edge##intra( h, pixuv + 4*edge*(dir?stride2uv:1),\
stride2uv, bs[dir][edge], chroma_qp, a, b, 0,\
stride2uv, bs[dir][edge], chroma_qp, a, b, 0,\
h->loopf.deblock_luma##intra[dir] );\
}\
- else if( CHROMA_FORMAT == CHROMA_420 && !(edge & 1) )\
+ else if( chroma_format == CHROMA_420 && !(edge & 1) )\
{\
deblock_edge##intra( h, pixuv + edge*(dir?2*stride2uv:4),\
stride2uv, bs[dir][edge], chroma_qp, a, b, 1,\
h->loopf.deblock_chroma##intra[dir] );\
}\
}\
- if( CHROMA_FORMAT == CHROMA_422 && (dir || !(edge & 1)) )\
+ if( chroma_format == CHROMA_422 && (dir || !(edge & 1)) )\
{\
deblock_edge##intra( h, pixuv + edge*(dir?4*stride2uv:4),\
stride2uv, bs[dir][edge], chroma_qp, a, b, 1,\
if( intra_cur || IS_INTRA( h->mb.type[h->mb.i_mb_left_xy[0]] ) )
{
deblock_edge_intra( h, pixy, 2*stridey, bs[0][0], luma_qp[0], a, b, 0, luma_intra_deblock );
- deblock_edge_intra( h, pixuv, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_intra_deblock );
- if( chroma444 )
- deblock_edge_intra( h, pixuv + uvdiff, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_intra_deblock );
+ if( chroma_format )
+ {
+ deblock_edge_intra( h, pixuv, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_intra_deblock );
+ if( chroma444 )
+ deblock_edge_intra( h, pixuv + uvdiff, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_intra_deblock );
+ }
}
else
{
deblock_edge( h, pixy, 2*stridey, bs[0][0], luma_qp[0], a, b, 0, luma_deblock );
- deblock_edge( h, pixuv, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_deblock );
- if( chroma444 )
- deblock_edge( h, pixuv + uvdiff, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_deblock );
+ if( chroma_format )
+ {
+ deblock_edge( h, pixuv, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_deblock );
+ if( chroma444 )
+ deblock_edge( h, pixuv + uvdiff, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_deblock );
+ }
}
int offy = MB_INTERLACED ? 4 : 0;
if( intra_cur || IS_INTRA( h->mb.type[h->mb.i_mb_left_xy[1]] ) )
{
deblock_edge_intra( h, pixy + (stridey<<offy), 2*stridey, bs[0][4], luma_qp[1], a, b, 0, luma_intra_deblock );
- deblock_edge_intra( h, pixuv + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_intra_deblock );
- if( chroma444 )
- deblock_edge_intra( h, pixuv + uvdiff + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_intra_deblock );
+ if( chroma_format )
+ {
+ deblock_edge_intra( h, pixuv + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_intra_deblock );
+ if( chroma444 )
+ deblock_edge_intra( h, pixuv + uvdiff + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_intra_deblock );
+ }
}
else
{
deblock_edge( h, pixy + (stridey<<offy), 2*stridey, bs[0][4], luma_qp[1], a, b, 0, luma_deblock );
- deblock_edge( h, pixuv + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_deblock );
- if( chroma444 )
- deblock_edge( h, pixuv + uvdiff + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_deblock );
+ if( chroma_format )
+ {
+ deblock_edge( h, pixuv + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_deblock );
+ if( chroma444 )
+ deblock_edge( h, pixuv + uvdiff + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_deblock );
+ }
}
}
else
deblock_edge( h, pixuv + j*strideuv, 2*strideuv, bs[1][4*j], qpc_top, a, b, 0, h->loopf.deblock_luma[1] );
deblock_edge( h, pixuv + uvdiff + j*strideuv, 2*strideuv, bs[1][4*j], qpc_top, a, b, 0, h->loopf.deblock_luma[1] );
}
- else
+ else if( chroma_format )
deblock_edge( h, pixuv + j*strideuv, 2*strideuv, bs[1][4*j], qpc_top, a, b, 1, h->loopf.deblock_chroma[1] );
}
}
static int frame_internal_csp( int external_csp )
{
- switch( external_csp & X264_CSP_MASK )
- {
- case X264_CSP_NV12:
- case X264_CSP_NV21:
- case X264_CSP_I420:
- case X264_CSP_YV12:
- return X264_CSP_NV12;
- case X264_CSP_NV16:
- case X264_CSP_I422:
- case X264_CSP_YV16:
- case X264_CSP_YUYV:
- case X264_CSP_UYVY:
- case X264_CSP_V210:
- return X264_CSP_NV16;
- case X264_CSP_I444:
- case X264_CSP_YV24:
- case X264_CSP_BGR:
- case X264_CSP_BGRA:
- case X264_CSP_RGB:
- return X264_CSP_I444;
- default:
- return X264_CSP_NONE;
- }
+ int csp = external_csp & X264_CSP_MASK;
+ if( csp == X264_CSP_I400 )
+ return X264_CSP_I400;
+ if( csp >= X264_CSP_I420 && csp < X264_CSP_I422 )
+ return X264_CSP_NV12;
+ if( csp >= X264_CSP_I422 && csp < X264_CSP_I444 )
+ return X264_CSP_NV16;
+ if( csp >= X264_CSP_I444 && csp <= X264_CSP_RGB )
+ return X264_CSP_I444;
+ return X264_CSP_NONE;
}
static x264_frame_t *frame_new( x264_t *h, int b_fdec )
frame->i_stride[i] = i_stride;
}
}
+ else if( i_csp == X264_CSP_I400 )
+ {
+ luma_plane_count = 1;
+ frame->i_plane = 1;
+ frame->i_width[0] = i_width;
+ frame->i_lines[0] = i_lines;
+ frame->i_stride[0] = i_stride;
+ }
else
goto fail;
(pixel*)pix[2], stride[2]/sizeof(pixel),
h->param.i_width>>1, h->param.i_height>>v_shift );
}
- else //if( i_csp == X264_CSP_I444 || i_csp == X264_CSP_YV24 )
+ else if( i_csp == X264_CSP_I444 || i_csp == X264_CSP_YV24 )
{
get_plane_ptr( h, src, &pix[1], &stride[1], i_csp==X264_CSP_I444 ? 1 : 2, 0, 0 );
get_plane_ptr( h, src, &pix[2], &stride[2], i_csp==X264_CSP_I444 ? 2 : 1, 0, 0 );
MC_LUMA( 0, 1 );
MC_LUMA( 0, 2 );
}
- else
+ else if( CHROMA_FORMAT )
{
int v_shift = CHROMA_V_SHIFT;
// Chroma in 4:2:0 is offset if MCing from a field of opposite parity
MC_LUMA( 1, 1 );
MC_LUMA( 1, 2 );
}
- else
+ else if( CHROMA_FORMAT )
{
int v_shift = CHROMA_V_SHIFT;
if( v_shift & MB_INTERLACED & i_ref )
MC_LUMA_BI( 1 );
MC_LUMA_BI( 2 );
}
- else
+ else if( CHROMA_FORMAT )
{
int v_shift = CHROMA_V_SHIFT;
if( v_shift & MB_INTERLACED & i_ref0 )
*/
h->mb.pic.p_fenc[0] = h->mb.pic.fenc_buf;
h->mb.pic.p_fdec[0] = h->mb.pic.fdec_buf + 2*FDEC_STRIDE;
- h->mb.pic.p_fenc[1] = h->mb.pic.fenc_buf + 16*FENC_STRIDE;
- h->mb.pic.p_fdec[1] = h->mb.pic.fdec_buf + 20*FDEC_STRIDE;
- if( CHROMA444 )
- {
- h->mb.pic.p_fenc[2] = h->mb.pic.fenc_buf + 32*FENC_STRIDE;
- h->mb.pic.p_fdec[2] = h->mb.pic.fdec_buf + 38*FDEC_STRIDE;
- }
- else
+ if( CHROMA_FORMAT )
{
- h->mb.pic.p_fenc[2] = h->mb.pic.fenc_buf + 16*FENC_STRIDE + 8;
- h->mb.pic.p_fdec[2] = h->mb.pic.fdec_buf + 20*FDEC_STRIDE + 16;
+ h->mb.pic.p_fenc[1] = h->mb.pic.fenc_buf + 16*FENC_STRIDE;
+ h->mb.pic.p_fdec[1] = h->mb.pic.fdec_buf + 20*FDEC_STRIDE;
+ if( CHROMA444 )
+ {
+ h->mb.pic.p_fenc[2] = h->mb.pic.fenc_buf + 32*FENC_STRIDE;
+ h->mb.pic.p_fdec[2] = h->mb.pic.fdec_buf + 38*FDEC_STRIDE;
+ }
+ else
+ {
+ h->mb.pic.p_fenc[2] = h->mb.pic.fenc_buf + 16*FENC_STRIDE + 8;
+ h->mb.pic.p_fdec[2] = h->mb.pic.fdec_buf + 20*FDEC_STRIDE + 16;
+ }
}
}
macroblock_load_pic_pointers( h, mb_x, mb_y, 1, 0, 0 );
macroblock_load_pic_pointers( h, mb_x, mb_y, 2, 0, 0 );
}
- else
+ else if( CHROMA_FORMAT )
{
x264_copy_column8( h->mb.pic.p_fdec[1]-1+ 4*FDEC_STRIDE, h->mb.pic.p_fdec[1]+ 7+ 4*FDEC_STRIDE );
x264_copy_column8( h->mb.pic.p_fdec[2]-1+ 4*FDEC_STRIDE, h->mb.pic.p_fdec[2]+ 7+ 4*FDEC_STRIDE );
macroblock_load_pic_pointers( h, mb_x, mb_y, 1, 0, 1 );
macroblock_load_pic_pointers( h, mb_x, mb_y, 2, 0, 1 );
}
- else
+ else if( CHROMA_FORMAT )
macroblock_load_pic_pointers( h, mb_x, mb_y, 1, 1, 1 );
}
memcpy( &h->intra_border_backup[backup_dst][1][mb_x*16 ], h->mb.pic.p_fdec[1]+FDEC_STRIDE*15, 16*sizeof(pixel) );
memcpy( &h->intra_border_backup[backup_dst][2][mb_x*16 ], h->mb.pic.p_fdec[2]+FDEC_STRIDE*15, 16*sizeof(pixel) );
}
- else
+ else if( CHROMA_FORMAT )
{
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, 16*sizeof(pixel) );
memcpy( &h->intra_border_backup[backup_dst][2][mb_x*16 ], h->mb.pic.p_fdec[2]+backup_src, 16*sizeof(pixel) );
}
- else
+ else if( CHROMA_FORMAT )
{
if( CHROMA_FORMAT == CHROMA_420 )
backup_src = (MB_INTERLACED ? 3 : 6) * FDEC_STRIDE;
macroblock_store_pic( h, h->mb.i_mb_x, h->mb.i_mb_y, 1, 0, 1 );
macroblock_store_pic( h, h->mb.i_mb_x, h->mb.i_mb_y, 2, 0, 1 );
}
- else
+ else if( CHROMA_FORMAT )
macroblock_store_pic( h, h->mb.i_mb_x, h->mb.i_mb_y, 1, 1, 1 );
}
else
macroblock_store_pic( h, h->mb.i_mb_x, h->mb.i_mb_y, 1, 0, 0 );
macroblock_store_pic( h, h->mb.i_mb_x, h->mb.i_mb_y, 2, 0, 0 );
}
- else
+ else if( CHROMA_FORMAT )
macroblock_store_pic( h, h->mb.i_mb_x, h->mb.i_mb_y, 1, 1, 0 );
}
pf->hpel_filter = hpel_filter;
+ pf->prefetch_fenc_400 = prefetch_fenc_null;
pf->prefetch_fenc_420 = prefetch_fenc_null;
pf->prefetch_fenc_422 = prefetch_fenc_null;
pf->prefetch_ref = prefetch_ref_null;
/* prefetch the next few macroblocks of fenc or fdec */
void (*prefetch_fenc) ( pixel *pix_y, intptr_t stride_y, pixel *pix_uv, intptr_t stride_uv, int mb_x );
+ void (*prefetch_fenc_400)( pixel *pix_y, intptr_t stride_y, pixel *pix_uv, intptr_t stride_uv, int mb_x );
void (*prefetch_fenc_420)( pixel *pix_y, intptr_t stride_y, pixel *pix_uv, intptr_t stride_uv, int mb_x );
void (*prefetch_fenc_422)( pixel *pix_y, intptr_t stride_y, pixel *pix_uv, intptr_t stride_uv, int mb_x );
/* prefetch the next few macroblocks of a hpel reference frame */
PREFETCH_FENC 420
PREFETCH_FENC 422
+%if ARCH_X86_64
+ DECLARE_REG_TMP 4
+%else
+ DECLARE_REG_TMP 2
+%endif
+
+cglobal prefetch_fenc_400, 2,3
+ movifnidn t0d, r4m
+ FIX_STRIDES r1
+ and t0d, 3
+ imul t0d, r1d
+ lea r0, [r0+t0*4+64*SIZEOF_PIXEL]
+ prefetcht0 [r0]
+ prefetcht0 [r0+r1]
+ lea r0, [r0+r1*2]
+ prefetcht0 [r0]
+ prefetcht0 [r0+r1]
+ RET
+
;-----------------------------------------------------------------------------
; void prefetch_ref( pixel *pix, intptr_t stride, int parity )
;-----------------------------------------------------------------------------
void x264_mc_copy_w16_avx( uint16_t *, intptr_t, uint16_t *, intptr_t, int );
#define x264_mc_copy_w16_aligned_avx x264_template(mc_copy_w16_aligned_avx)
void x264_mc_copy_w16_aligned_avx( uint16_t *, intptr_t, uint16_t *, intptr_t, int );
+#define x264_prefetch_fenc_400_mmx2 x264_template(prefetch_fenc_400_mmx2)
+void x264_prefetch_fenc_400_mmx2( pixel *, intptr_t, pixel *, intptr_t, int );
#define x264_prefetch_fenc_420_mmx2 x264_template(prefetch_fenc_420_mmx2)
void x264_prefetch_fenc_420_mmx2( pixel *, intptr_t, pixel *, intptr_t, int );
#define x264_prefetch_fenc_422_mmx2 x264_template(prefetch_fenc_422_mmx2)
if( !(cpu&X264_CPU_MMX2) )
return;
+ pf->prefetch_fenc_400 = x264_prefetch_fenc_400_mmx2;
pf->prefetch_fenc_420 = x264_prefetch_fenc_420_mmx2;
pf->prefetch_fenc_422 = x264_prefetch_fenc_422_mmx2;
pf->prefetch_ref = x264_prefetch_ref_mmx2;
--disable-win32thread disable win32threads (windows only)
--disable-interlaced disable interlaced encoding support
--bit-depth=BIT_DEPTH set output bit depth (8, 10, all) [all]
- --chroma-format=FORMAT output chroma format (420, 422, 444, all) [all]
+ --chroma-format=FORMAT output chroma format (400, 420, 422, 444, all) [all]
Advanced options:
--disable-asm disable platform-specific assembly optimizations
;;
--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."
+ if [ $chroma_format != "400" -a $chroma_format != "420" -a $chroma_format != "422" -a $chroma_format != "444" -a $chroma_format != "all" ]; then
+ echo "Supplied chroma format must be 400, 420, 422, 444 or all."
exit 1
fi
;;
/* I: Intra part */
a->i_satd_i16x16 =
a->i_satd_i8x8 =
- a->i_satd_i4x4 =
- a->i_satd_chroma = COST_MAX;
+ a->i_satd_i4x4 = COST_MAX;
+ a->i_satd_chroma = CHROMA_FORMAT ? COST_MAX : 0;
/* non-RD PCM decision is inaccurate (as is psy-rd), so don't do it.
* PCM cost can overflow with high lambda2, so cap it at COST_MAX. */
}
/* RD selection for chroma prediction */
- if( !CHROMA444 )
+ if( CHROMA_FORMAT == CHROMA_420 || CHROMA_FORMAT == CHROMA_422 )
{
const int8_t *predict_mode = predict_chroma_mode_available( h->mb.i_neighbour_intra );
if( predict_mode[1] >= 0 )
{
if( CHROMA444 )
macroblock_write_cabac_internal( h, cb, 3, 0 );
- else
+ else if( CHROMA_FORMAT )
macroblock_write_cabac_internal( h, cb, 1, 1 );
+ else
+ macroblock_write_cabac_internal( h, cb, 1, 0 );
}
#if RDO_SKIP_BS
bs_t *s = &h->out.bs;
const int i_mb_type = h->mb.i_type;
int plane_count = CHROMA444 ? 3 : 1;
- int chroma = !CHROMA444;
+ int chroma = CHROMA_FORMAT == CHROMA_420 || CHROMA_FORMAT == CHROMA_422;
#if RDO_SKIP_BS
s->i_bits_encoded = 0;
for( int p = 0; p < (CHROMA444 ? 3 : 1); p++ )
for( int y = 0; y < h->param.i_height; y++ )
fwrite( &h->fdec->plane[p][y*h->fdec->i_stride[p]], sizeof(pixel), h->param.i_width, f );
- if( !CHROMA444 )
+ if( CHROMA_FORMAT == CHROMA_420 || CHROMA_FORMAT == CHROMA_422 )
{
int cw = h->param.i_width>>1;
int ch = h->param.i_height>>CHROMA_V_SHIFT;
{
sh->b_weighted_pred = sh->weight[0][0].weightfn || sh->weight[0][1].weightfn || sh->weight[0][2].weightfn;
/* pred_weight_table() */
- bs_write_ue( s, sh->weight[0][0].i_denom );
- bs_write_ue( s, sh->weight[0][1].i_denom );
+ bs_write_ue( s, sh->weight[0][0].i_denom ); /* luma_log2_weight_denom */
+ if( sh->sps->i_chroma_format_idc )
+ bs_write_ue( s, sh->weight[0][1].i_denom ); /* chroma_log2_weight_denom */
for( int i = 0; i < sh->i_num_ref_idx_l0_active; i++ )
{
int luma_weight_l0_flag = !!sh->weight[i][0].weightfn;
- int chroma_weight_l0_flag = !!sh->weight[i][1].weightfn || !!sh->weight[i][2].weightfn;
bs_write1( s, luma_weight_l0_flag );
if( luma_weight_l0_flag )
{
bs_write_se( s, sh->weight[i][0].i_scale );
bs_write_se( s, sh->weight[i][0].i_offset );
}
- bs_write1( s, chroma_weight_l0_flag );
- if( chroma_weight_l0_flag )
+ if( sh->sps->i_chroma_format_idc )
{
- for( int j = 1; j < 3; j++ )
+ int chroma_weight_l0_flag = sh->weight[i][1].weightfn || sh->weight[i][2].weightfn;
+ bs_write1( s, chroma_weight_l0_flag );
+ if( chroma_weight_l0_flag )
{
- bs_write_se( s, sh->weight[i][j].i_scale );
- bs_write_se( s, sh->weight[i][j].i_offset );
+ for( int j = 1; j < 3; j++ )
+ {
+ bs_write_se( s, sh->weight[i][j].i_scale );
+ bs_write_se( s, sh->weight[i][j].i_offset );
+ }
}
}
}
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_I422 )
+ if( CHROMA_FORMAT != CHROMA_400 && i_csp == X264_CSP_I400 )
+ {
+ x264_log( h, X264_LOG_ERROR, "not compiled with 4:0:0 support\n" );
+ return -1;
+ }
+ else if( CHROMA_FORMAT != CHROMA_420 && i_csp >= X264_CSP_I420 && i_csp < X264_CSP_I422 )
{
x264_log( h, X264_LOG_ERROR, "not compiled with 4:2:0 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/NV21/I422/YV16/NV16/YUYV/UYVY/"
+ x264_log( h, X264_LOG_ERROR, "invalid CSP (only I400/I420/YV12/NV12/NV21/I422/YV16/NV16/YUYV/UYVY/"
"I444/YV24/BGR/BGRA/RGB supported)\n" );
return -1;
}
- int w_mod = i_csp < X264_CSP_I444 ? 2 : 1;
- int h_mod = (i_csp < X264_CSP_I422 ? 2 : 1) << PARAM_INTERLACED;
+ int w_mod = 1;
+ int h_mod = 1 << PARAM_INTERLACED;
+ if( i_csp == X264_CSP_I400 )
+ {
+ h->param.analyse.i_chroma_qp_offset = 0;
+ h->param.analyse.b_chroma_me = 0;
+ h->param.vui.i_colmatrix = 2; /* undefined */
+ }
+ else if( i_csp < X264_CSP_I444 )
+ {
+ w_mod = 2;
+ if( i_csp < X264_CSP_I422 )
+ h_mod *= 2;
+ }
+
if( h->param.i_width % w_mod )
{
x264_log( h, X264_LOG_ERROR, "width not divisible by %d (%dx%d)\n",
switch( CHROMA_FORMAT )
{
+ case CHROMA_400:
+ h->mc.prefetch_fenc = h->mc.prefetch_fenc_400;
+ break;
case CHROMA_420:
memcpy( h->predict_chroma, h->predict_8x8c, sizeof(h->predict_chroma) );
h->mc.prefetch_fenc = h->mc.prefetch_fenc_420;
(h->sps->i_profile_idc == PROFILE_BASELINE || h->sps->i_profile_idc == PROFILE_MAIN) ) )
strcpy( level, "1b" );
- if( h->sps->i_profile_idc < PROFILE_HIGH10 )
- {
- x264_log( h, X264_LOG_INFO, "profile %s, level %s\n",
- profile, level );
- }
- else
- {
- static const char * const subsampling[4] = { "4:0:0", "4:2:0", "4:2:2", "4:4:4" };
- x264_log( h, X264_LOG_INFO, "profile %s, level %s, %s %d-bit\n",
- profile, level, subsampling[CHROMA_FORMAT], BIT_DEPTH );
- }
+ static const char * const subsampling[4] = { "4:0:0", "4:2:0", "4:2:2", "4:4:4" };
+ x264_log( h, X264_LOG_INFO, "profile %s, level %s, %s, %d-bit\n",
+ profile, level, subsampling[CHROMA_FORMAT], BIT_DEPTH );
return h;
fail:
}
buf[0] = 0;
- int csize = CHROMA444 ? 4 : 1;
- if( i_mb_count != i_all_intra )
- sprintf( buf, " inter: %.1f%% %.1f%% %.1f%%",
- h->stat.i_mb_cbp[1] * 100.0 / ((i_mb_count - i_all_intra)*4),
- h->stat.i_mb_cbp[3] * 100.0 / ((i_mb_count - i_all_intra)*csize),
- h->stat.i_mb_cbp[5] * 100.0 / ((i_mb_count - i_all_intra)*csize) );
- x264_log( h, X264_LOG_INFO, "coded y,%s,%s intra: %.1f%% %.1f%% %.1f%%%s\n",
- CHROMA444?"u":"uvDC", CHROMA444?"v":"uvAC",
- h->stat.i_mb_cbp[0] * 100.0 / (i_all_intra*4),
- h->stat.i_mb_cbp[2] * 100.0 / (i_all_intra*csize),
- h->stat.i_mb_cbp[4] * 100.0 / (i_all_intra*csize), buf );
+ if( CHROMA_FORMAT )
+ {
+ int csize = CHROMA444 ? 4 : 1;
+ if( i_mb_count != i_all_intra )
+ sprintf( buf, " inter: %.1f%% %.1f%% %.1f%%",
+ h->stat.i_mb_cbp[1] * 100.0 / ((i_mb_count - i_all_intra)*4),
+ h->stat.i_mb_cbp[3] * 100.0 / ((i_mb_count - i_all_intra)*csize),
+ h->stat.i_mb_cbp[5] * 100.0 / ((i_mb_count - i_all_intra)*csize) );
+ x264_log( h, X264_LOG_INFO, "coded y,%s,%s intra: %.1f%% %.1f%% %.1f%%%s\n",
+ CHROMA444?"u":"uvDC", CHROMA444?"v":"uvAC",
+ h->stat.i_mb_cbp[0] * 100.0 / (i_all_intra*4),
+ h->stat.i_mb_cbp[2] * 100.0 / (i_all_intra*csize),
+ h->stat.i_mb_cbp[4] * 100.0 / (i_all_intra*csize), buf );
+ }
+ else
+ {
+ if( i_mb_count != i_all_intra )
+ sprintf( buf, " inter: %.1f%%", h->stat.i_mb_cbp[1] * 100.0 / ((i_mb_count - i_all_intra)*4) );
+ x264_log( h, X264_LOG_INFO, "coded y intra: %.1f%%%s\n",
+ h->stat.i_mb_cbp[0] * 100.0 / (i_all_intra*4), buf );
+ }
int64_t fixed_pred_modes[4][9] = {{0}};
int64_t sum_pred_modes[4] = {0};
fixed_pred_modes[3][3] * 100.0 / sum_pred_modes[3] );
if( h->param.analyse.i_weighted_pred >= X264_WEIGHTP_SIMPLE && h->stat.i_frame_count[SLICE_TYPE_P] > 0 )
- x264_log( h, X264_LOG_INFO, "Weighted P-Frames: Y:%.1f%% UV:%.1f%%\n",
- h->stat.i_wpred[0] * 100.0 / h->stat.i_frame_count[SLICE_TYPE_P],
- h->stat.i_wpred[1] * 100.0 / h->stat.i_frame_count[SLICE_TYPE_P] );
+ {
+ buf[0] = 0;
+ if( CHROMA_FORMAT )
+ sprintf( buf, " UV:%.1f%%", h->stat.i_wpred[1] * 100.0 / h->stat.i_frame_count[SLICE_TYPE_P] );
+ x264_log( h, X264_LOG_INFO, "Weighted P-Frames: Y:%.1f%%%s\n",
+ h->stat.i_wpred[0] * 100.0 / h->stat.i_frame_count[SLICE_TYPE_P], buf );
+ }
for( int i_list = 0; i_list < 2; i_list++ )
for( int i_slice = 0; i_slice < 2; i_slice++ )
{
if( CHROMA444 )
macroblock_encode_internal( h, 3, 0 );
- else
+ else if( CHROMA_FORMAT )
macroblock_encode_internal( h, 1, 1 );
+ else
+ macroblock_encode_internal( h, 1, 0 );
}
/*****************************************************************************
int x264_macroblock_probe_skip( x264_t *h, int b_bidir )
{
- if( CHROMA_FORMAT == CHROMA_444 )
- return macroblock_probe_skip_internal( h, b_bidir, 3, CHROMA_444 );
+ if( CHROMA_FORMAT == CHROMA_420 )
+ return macroblock_probe_skip_internal( h, b_bidir, 1, CHROMA_420 );
else if( CHROMA_FORMAT == CHROMA_422 )
return macroblock_probe_skip_internal( h, b_bidir, 1, CHROMA_422 );
+ else if( CHROMA_FORMAT == CHROMA_444 )
+ return macroblock_probe_skip_internal( h, b_bidir, 3, CHROMA_444 );
else
- return macroblock_probe_skip_internal( h, b_bidir, 1, CHROMA_420 );
+ return macroblock_probe_skip_internal( h, b_bidir, 1, CHROMA_400 );
}
/****************************************************************************
void x264_macroblock_encode_p8x8( x264_t *h, int i8 )
{
- if( CHROMA444 )
- macroblock_encode_p8x8_internal( h, i8, 3, CHROMA_444 );
+ if( CHROMA_FORMAT == CHROMA_420 )
+ macroblock_encode_p8x8_internal( h, i8, 1, CHROMA_420 );
else if( CHROMA_FORMAT == CHROMA_422 )
macroblock_encode_p8x8_internal( h, i8, 1, CHROMA_422 );
+ else if( CHROMA_FORMAT == CHROMA_444 )
+ macroblock_encode_p8x8_internal( h, i8, 3, CHROMA_444 );
else
- macroblock_encode_p8x8_internal( h, i8, 1, CHROMA_420 );
+ macroblock_encode_p8x8_internal( h, i8, 1, CHROMA_400 );
}
/*****************************************************************************
src[2][list][i] = h->mc.get_ref( pixv_buf[list][i], &stride[2][list][i], &m->p_fref[8],\
m->i_stride[2], mvx, mvy, bw, bh, x264_weight_none );\
}\
- else\
+ else if( CHROMA_FORMAT )\
h->mc.mc_chroma( pixu_buf[list][i], pixv_buf[list][i], 8, m->p_fref[4], m->i_stride[1],\
mvx, 2*(mvy+mv##list##y_offset)>>chroma_v_shift, bw>>1, bh>>chroma_v_shift );\
}\
h->mc.avg[i_pixel]( pixu, FDEC_STRIDE, src[1][0][i0], stride[1][0][i0], src[1][1][i1], stride[1][1][i1], i_weight );
h->mc.avg[i_pixel]( pixv, FDEC_STRIDE, src[2][0][i0], stride[2][0][i0], src[2][1][i1], stride[2][1][i1], i_weight );
}
- else
+ else if( CHROMA_FORMAT )
{
h->mc.avg[chromapix]( pixu, FDEC_STRIDE, pixu_buf[0][i0], 8, pixu_buf[1][i1], 8, i_weight );
h->mc.avg[chromapix]( pixv, FDEC_STRIDE, pixv_buf[0][i0], 8, pixv_buf[1][i1], 8, i_weight );
h->mc.mc_luma( pixu, FDEC_STRIDE, &m->p_fref[4], m->i_stride[1], mx, my, bw, bh, &m->weight[1] ); \
h->mc.mc_luma( pixv, FDEC_STRIDE, &m->p_fref[8], m->i_stride[2], mx, my, bw, bh, &m->weight[2] ); \
} \
- else if( m->i_pixel <= PIXEL_8x8 ) \
+ else if( CHROMA_FORMAT && m->i_pixel <= PIXEL_8x8 ) \
{ \
h->mc.mc_chroma( pixu, pixv, FDEC_STRIDE, m->p_fref[4], m->i_stride[1], \
mx, 2*(my+mvy_offset)>>chroma_v_shift, bw>>1, bh>>chroma_v_shift ); \
var_interlaced += ac_energy_plane( h, mb_x, mb_y, frame, 2, 0, 1, 1 );
var_progressive += ac_energy_plane( h, mb_x, mb_y, frame, 2, 0, 0, 0 );
}
- else
+ else if( CHROMA_FORMAT )
{
var_interlaced += ac_energy_plane( h, mb_x, mb_y, frame, 1, 1, 1, 1 );
var_progressive += ac_energy_plane( h, mb_x, mb_y, frame, 1, 1, 0, 0 );
var += ac_energy_plane( h, mb_x, mb_y, frame, 1, 0, PARAM_INTERLACED, 1 );
var += ac_energy_plane( h, mb_x, mb_y, frame, 2, 0, PARAM_INTERLACED, 1 );
}
- else
+ else if( CHROMA_FORMAT )
var += ac_energy_plane( h, mb_x, mb_y, frame, 1, 1, PARAM_INTERLACED, 1 );
}
x264_emms();
static inline int ssd_mb( x264_t *h )
{
- int chroma_size = h->luma2chroma_pixel[PIXEL_16x16];
- int chroma_ssd = ssd_plane(h, chroma_size, 1, 0, 0) + ssd_plane(h, chroma_size, 2, 0, 0);
- chroma_ssd = ((uint64_t)chroma_ssd * h->mb.i_chroma_lambda2_offset + 128) >> 8;
- return ssd_plane(h, PIXEL_16x16, 0, 0, 0) + chroma_ssd;
+ int i_ssd = ssd_plane( h, PIXEL_16x16, 0, 0, 0 );
+ if( CHROMA_FORMAT )
+ {
+ int chroma_size = h->luma2chroma_pixel[PIXEL_16x16];
+ int chroma_ssd = ssd_plane( h, chroma_size, 1, 0, 0 ) + ssd_plane( h, chroma_size, 2, 0, 0 );
+ i_ssd += ((uint64_t)chroma_ssd * h->mb.i_chroma_lambda2_offset + 128) >> 8;
+ }
+ return i_ssd;
}
static int rd_cost_mb( x264_t *h, int i_lambda2 )
int ssd_x = 8*(i8&1);
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>>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( CHROMA_FORMAT )
+ {
+ int chroma_size = h->luma2chroma_pixel[i_pixel];
+ int chroma_ssd = ssd_plane( h, chroma_size, 1, ssd_x>>CHROMA_H_SHIFT, ssd_y>>CHROMA_V_SHIFT )
+ + ssd_plane( h, chroma_size, 2, ssd_x>>CHROMA_H_SHIFT, ssd_y>>CHROMA_V_SHIFT );
+ i_ssd += ((uint64_t)chroma_ssd * h->mb.i_chroma_lambda2_offset + 128) >> 8;
+ }
if( h->param.b_cabac )
{
sps->i_mb_width = ( param->i_width + 15 ) / 16;
sps->i_mb_height= ( param->i_height + 15 ) / 16;
sps->i_chroma_format_idc = csp >= X264_CSP_I444 ? CHROMA_444 :
- csp >= X264_CSP_I422 ? CHROMA_422 : CHROMA_420;
+ csp >= X264_CSP_I422 ? CHROMA_422 :
+ csp >= X264_CSP_I420 ? CHROMA_420 : CHROMA_400;
sps->b_qpprime_y_zero_transform_bypass = param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0;
if( sps->b_qpprime_y_zero_transform_bypass || sps->i_chroma_format_idc == CHROMA_444 )
sps->i_profile_idc = PROFILE_HIGH422;
else if( BIT_DEPTH > 8 )
sps->i_profile_idc = PROFILE_HIGH10;
- else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT )
+ else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT || sps->i_chroma_format_idc == CHROMA_400 )
sps->i_profile_idc = PROFILE_HIGH;
else if( param->b_cabac || param->i_bframe > 0 || param->b_interlaced || param->b_fake_interlaced || param->analyse.i_weighted_pred > 0 )
sps->i_profile_idc = PROFILE_MAIN;
sps->vui.i_transfer = ( param->vui.i_transfer >= 0 && param->vui.i_transfer <= 18 ? param->vui.i_transfer : 2 );
sps->vui.i_colmatrix = ( param->vui.i_colmatrix >= 0 && param->vui.i_colmatrix <= 14 ? param->vui.i_colmatrix :
( csp >= X264_CSP_BGR ? 0 : 2 ) );
- if( sps->vui.i_colorprim != 2 ||
- sps->vui.i_transfer != 2 ||
- sps->vui.i_colmatrix != 2 )
- {
+ if( sps->vui.i_colorprim != 2 || sps->vui.i_transfer != 2 || sps->vui.i_colmatrix != 2 )
sps->vui.b_color_description_present = 1;
- }
- if( sps->vui.i_vidformat != 5 ||
- sps->vui.b_fullrange ||
- sps->vui.b_color_description_present )
- {
+ if( sps->vui.i_vidformat != 5 || sps->vui.b_fullrange || sps->vui.b_color_description_present )
sps->vui.b_signal_type_present = 1;
- }
/* FIXME: not sufficient for interlaced video */
sps->vui.b_chroma_loc_info_present = param->vui.i_chroma_loc > 0 && param->vui.i_chroma_loc <= 5 &&
}
/* Don't check chroma in lookahead, or if there wasn't a luma weight. */
- for( int plane = 0; plane <= 2 && !( plane && ( !weights[0].weightfn || b_lookahead ) ); plane++ )
+ for( int plane = 0; plane < (CHROMA_FORMAT ? 3 : 1) && !( plane && ( !weights[0].weightfn || b_lookahead ) ); plane++ )
{
int minoff, minscale, mindenom;
unsigned int minscore, origscore;
static int depth_filter_csp_is_supported( int csp )
{
int csp_mask = csp & X264_CSP_MASK;
- return csp_mask == X264_CSP_I420 ||
+ return csp_mask == X264_CSP_I400 ||
+ csp_mask == X264_CSP_I420 ||
csp_mask == X264_CSP_I422 ||
csp_mask == X264_CSP_I444 ||
csp_mask == X264_CSP_YV12 ||
/* state of swapping chroma planes pre and post resize */
int pre_swap_chroma;
int post_swap_chroma;
+ int fast_mono; /* yuv with planar luma can be "converted" to monochrome by simply ignoring chroma */
int variable_input; /* input is capable of changing properties */
int working; /* we have already started working with frames */
frame_prop_t dst; /* desired output properties */
return csp&X264_CSP_MASK;
switch( csp&X264_CSP_MASK )
{
+ case X264_CSP_I400: return csp&X264_CSP_HIGH_DEPTH ? AV_PIX_FMT_GRAY16 : AV_PIX_FMT_GRAY8;
case X264_CSP_YV12: /* specially handled via swapping chroma */
case X264_CSP_I420: return csp&X264_CSP_HIGH_DEPTH ? AV_PIX_FMT_YUV420P16 : AV_PIX_FMT_YUV420P;
case X264_CSP_YV16: /* specially handled via swapping chroma */
{
// yuv-based
if( pix_desc->nb_components == 1 || pix_desc->nb_components == 2 ) // no chroma
- ret = X264_CSP_I420;
+ ret = X264_CSP_I400;
else if( pix_desc->log2_chroma_w && pix_desc->log2_chroma_h ) // reduced chroma width & height
ret = (pix_number_of_planes( pix_desc ) == 2) ? X264_CSP_NV12 : X264_CSP_I420;
else if( pix_desc->log2_chroma_w ) // reduced chroma width only
return 0;
/* also warn if the resizer was initialized after the first frame */
if( h->ctx || h->working )
+ {
x264_cli_log( NAME, X264_LOG_WARNING, "stream properties changed at pts %"PRId64"\n", in->pts );
+ h->fast_mono = 0;
+ }
h->scale = input_prop;
- if( !h->buffer_allocated )
+ if( !h->buffer_allocated && !h->fast_mono )
{
if( x264_cli_pic_alloc_aligned( &h->buffer, h->dst_csp, h->dst.width, h->dst.height ) )
return -1;
h->input_range ? "PC" : "TV", h->dst.range ? "PC" : "TV" );
h->dst_csp |= info->csp & X264_CSP_VFLIP; // preserve vflip
+ if( dst_csp == X264_CSP_I400 &&
+ ((src_csp >= X264_CSP_I420 && src_csp <= X264_CSP_NV16) || src_csp == X264_CSP_I444 || src_csp == X264_CSP_YV24) &&
+ h->dst.width == info->width && h->dst.height == info->height && h->dst.range == h->input_range )
+ h->fast_mono = 1; /* use the input luma plane as is */
+
/* if the input is not variable, initialize the context */
if( !h->variable_input )
{
h->working = 1;
if( h->pre_swap_chroma )
XCHG( uint8_t*, output->img.plane[1], output->img.plane[2] );
- if( h->ctx )
+ if( h->ctx && !h->fast_mono )
{
sws_scale( h->ctx, (const uint8_t* const*)output->img.plane, output->img.stride,
0, output->img.height, h->buffer.img.plane, h->buffer.img.stride );
#define AVS_IS_YUV420P16( vi ) (0)
#define AVS_IS_YUV422P16( vi ) (0)
#define AVS_IS_YUV444P16( vi ) (0)
+#define AVS_IS_Y( vi ) (0)
+#define AVS_IS_Y16( vi ) (0)
#else
#define AVS_IS_AVISYNTHPLUS (h->func.avs_is_420 && h->func.avs_is_422 && h->func.avs_is_444)
#define AVS_IS_420( vi ) (h->func.avs_is_420 ? h->func.avs_is_420( vi ) : avs_is_yv12( vi ))
#define AVS_IS_YUV420P16( vi ) (h->func.avs_is_yuv420p16 && h->func.avs_is_yuv420p16( vi ))
#define AVS_IS_YUV422P16( vi ) (h->func.avs_is_yuv422p16 && h->func.avs_is_yuv422p16( vi ))
#define AVS_IS_YUV444P16( vi ) (h->func.avs_is_yuv444p16 && h->func.avs_is_yuv444p16( vi ))
+#define AVS_IS_Y( vi ) (h->func.avs_is_y ? h->func.avs_is_y( vi ) : avs_is_y8( vi ))
+#define AVS_IS_Y16( vi ) (h->func.avs_is_y16 && h->func.avs_is_y16( vi ))
#endif
/* generate a filter sequence to try based on the filename extension */
if( !strcasecmp( filename_ext, "avs" ) )
{
res = h->func.avs_invoke( h->env, "Import", arg, NULL );
- FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_string( res ) );
+ FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_error( res ) );
/* check if the user is using a multi-threaded script and apply distributor if necessary.
adapted from avisynth's vfw interface */
AVS_Value mt_test = h->func.avs_invoke( h->env, "GetMTMode", avs_new_value_bool( 0 ), NULL );
{
x264_cli_log( "avs", X264_LOG_WARNING, "detected fieldbased (separated) input, weaving to frames\n" );
AVS_Value tmp = h->func.avs_invoke( h->env, "Weave", res, NULL );
- FAIL_IF_ERROR( avs_is_error( tmp ), "couldn't weave fields into frames\n" );
+ FAIL_IF_ERROR( avs_is_error( tmp ), "couldn't weave fields into frames: %s\n", avs_as_error( tmp ) );
res = update_clip( h, &vi, tmp, res );
info->interlaced = 1;
info->tff = avs_is_tff( vi );
}
#if !HAVE_SWSCALE
/* if swscale is not available, convert the CSP if necessary */
- FAIL_IF_ERROR( avs_version < 2.6f && (opt->output_csp == X264_CSP_I422 || opt->output_csp == X264_CSP_I444),
- "avisynth >= 2.6 is required for i422/i444 output\n" );
- if( (opt->output_csp == X264_CSP_I420 && !AVS_IS_420( vi )) ||
+ FAIL_IF_ERROR( avs_version < 2.6f && (opt->output_csp == X264_CSP_I400 || opt->output_csp == X264_CSP_I422 || opt->output_csp == X264_CSP_I444),
+ "avisynth >= 2.6 is required for i400/i422/i444 output\n" );
+ if( (opt->output_csp == X264_CSP_I400 && !AVS_IS_Y( vi )) ||
+ (opt->output_csp == X264_CSP_I420 && !AVS_IS_420( vi )) ||
(opt->output_csp == X264_CSP_I422 && !AVS_IS_422( vi )) ||
(opt->output_csp == X264_CSP_I444 && !AVS_IS_444( vi )) ||
(opt->output_csp == X264_CSP_RGB && !avs_is_rgb( vi )) )
const char *csp;
if( AVS_IS_AVISYNTHPLUS )
{
- csp = opt->output_csp == X264_CSP_I420 ? "YUV420" :
+ csp = opt->output_csp == X264_CSP_I400 ? "Y" :
+ opt->output_csp == X264_CSP_I420 ? "YUV420" :
opt->output_csp == X264_CSP_I422 ? "YUV422" :
opt->output_csp == X264_CSP_I444 ? "YUV444" :
"RGB";
}
else
{
- csp = opt->output_csp == X264_CSP_I420 ? "YV12" :
+ csp = opt->output_csp == X264_CSP_I400 ? "Y8" :
+ opt->output_csp == X264_CSP_I420 ? "YV12" :
opt->output_csp == X264_CSP_I422 ? "YV16" :
opt->output_csp == X264_CSP_I444 ? "YV24" :
"RGB";
}
x264_cli_log( "avs", X264_LOG_WARNING, "converting input clip to %s\n", csp );
- FAIL_IF_ERROR( opt->output_csp < X264_CSP_I444 && (vi->width&1),
- "input clip width not divisible by 2 (%dx%d)\n", vi->width, vi->height );
- FAIL_IF_ERROR( opt->output_csp == X264_CSP_I420 && info->interlaced && (vi->height&3),
- "input clip height not divisible by 4 (%dx%d)\n", vi->width, vi->height );
- FAIL_IF_ERROR( (opt->output_csp == X264_CSP_I420 || info->interlaced) && (vi->height&1),
- "input clip height not divisible by 2 (%dx%d)\n", vi->width, vi->height );
+ if( opt->output_csp != X264_CSP_I400 )
+ {
+ FAIL_IF_ERROR( opt->output_csp < X264_CSP_I444 && (vi->width&1),
+ "input clip width not divisible by 2 (%dx%d)\n", vi->width, vi->height );
+ FAIL_IF_ERROR( opt->output_csp == X264_CSP_I420 && info->interlaced && (vi->height&3),
+ "input clip height not divisible by 4 (%dx%d)\n", vi->width, vi->height );
+ FAIL_IF_ERROR( (opt->output_csp == X264_CSP_I420 || info->interlaced) && (vi->height&1),
+ "input clip height not divisible by 2 (%dx%d)\n", vi->width, vi->height );
+ }
char conv_func[16];
snprintf( conv_func, sizeof(conv_func), "ConvertTo%s", csp );
- char matrix[7] = "";
- int arg_count = 2;
+ AVS_Value arg_arr[3];
+ const char *arg_name[3];
+ int arg_count = 1;
+ arg_arr[0] = res;
+ arg_name[0] = NULL;
+ if( opt->output_csp != X264_CSP_I400 )
+ {
+ arg_arr[arg_count] = avs_new_value_bool( info->interlaced );
+ arg_name[arg_count] = "interlaced";
+ arg_count++;
+ }
/* if doing a rgb <-> yuv conversion then range is handled via 'matrix'. though it's only supported in 2.56+ */
+ char matrix[7];
if( avs_version >= 2.56f && ((opt->output_csp == X264_CSP_RGB && avs_is_yuv( vi )) || (opt->output_csp != X264_CSP_RGB && avs_is_rgb( vi ))) )
{
// if converting from yuv, then we specify the matrix for the input, otherwise use the output's.
int use_pc_matrix = avs_is_yuv( vi ) ? opt->input_range == RANGE_PC : opt->output_range == RANGE_PC;
snprintf( matrix, sizeof(matrix), "%s601", use_pc_matrix ? "PC." : "Rec" ); /* FIXME: use correct coefficients */
+ arg_arr[arg_count] = avs_new_value_string( matrix );
+ arg_name[arg_count] = "matrix";
arg_count++;
// notification that the input range has changed to the desired one
opt->input_range = opt->output_range;
}
- const char *arg_name[] = { NULL, "interlaced", "matrix" };
- AVS_Value arg_arr[3];
- arg_arr[0] = res;
- arg_arr[1] = avs_new_value_bool( info->interlaced );
- arg_arr[2] = avs_new_value_string( matrix );
AVS_Value res2 = h->func.avs_invoke( h->env, conv_func, avs_new_value_array( arg_arr, arg_count ), arg_name );
- FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert input clip to %s\n", csp );
+ FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert input clip to %s: %s\n", csp, avs_as_error( res2 ) );
res = update_clip( h, &vi, res2, res );
}
/* if swscale is not available, change the range if necessary. This only applies to YUV-based CSPs however */
info->csp = X264_CSP_I420 | X264_CSP_HIGH_DEPTH;
else if( avs_is_yv12( vi ) )
info->csp = X264_CSP_I420;
-#if HAVE_SWSCALE
+ else if( AVS_IS_Y16( vi ) )
+ info->csp = X264_CSP_I400 | X264_CSP_HIGH_DEPTH;
+ else if( avs_is_y8( vi ) )
+ info->csp = X264_CSP_I400;
else if( avs_is_yuy2( vi ) )
- info->csp = AV_PIX_FMT_YUYV422 | X264_CSP_OTHER;
+ info->csp = X264_CSP_YUYV;
+#if HAVE_SWSCALE
else if( avs_is_yv411( vi ) )
info->csp = AV_PIX_FMT_YUV411P | X264_CSP_OTHER;
- else if( avs_is_y8( vi ) )
- info->csp = AV_PIX_FMT_GRAY8 | X264_CSP_OTHER;
#endif
else
{
#endif
const x264_cli_csp_t x264_cli_csps[] = {
+ [X264_CSP_I400] = { "i400", 1, { 1 }, { 1 }, 1, 1 },
[X264_CSP_I420] = { "i420", 3, { 1, .5, .5 }, { 1, .5, .5 }, 2, 2 },
[X264_CSP_I422] = { "i422", 3, { 1, .5, .5 }, { 1, 1, 1 }, 2, 1 },
[X264_CSP_I444] = { "i444", 3, { 1, 1, 1 }, { 1, 1, 1 }, 1, 1 },
static int parse_csp_and_depth( char *csp_name, int *bit_depth )
{
- int csp = X264_CSP_MAX;
+ int csp = X264_CSP_MAX;
/* Set colorspace from known variants */
- if( !strncmp( "420", csp_name, 3 ) )
+ if( !strncmp( "mono", csp_name, 4 ) )
+ csp = X264_CSP_I400;
+ else if( !strncmp( "420", csp_name, 3 ) )
csp = X264_CSP_I420;
else if( !strncmp( "422", csp_name, 3 ) )
csp = X264_CSP_I422;
csp = X264_CSP_I444;
/* Set high bit depth from known extensions */
- if( sscanf( csp_name, "%*d%*[pP]%d", bit_depth ) != 1 )
+ if( sscanf( csp_name, "mono%d", bit_depth ) != 1 &&
+ sscanf( csp_name, "%*d%*[pP]%d", bit_depth ) != 1 )
*bit_depth = 8;
return csp;
static const char * const log_level_names[] = { "none", "error", "warning", "info", "debug", 0 };
static const char * const output_csp_names[] =
{
+#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I400
+ "i400",
+#endif
#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420
"i420",
#endif
static const char * const chroma_format_names[] =
{
[0] = "all",
+ [X264_CSP_I400] = "i400",
[X264_CSP_I420] = "i420",
[X264_CSP_I422] = "i422",
[X264_CSP_I444] = "i444"
H0( " --profile <string> Force the limits of an H.264 profile\n"
" Overrides all settings.\n" );
H2(
-#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420
+#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT <= X264_CSP_I420
#if HAVE_BITDEPTH8
+#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420
" - baseline:\n"
" --no-8x8dct --bframes 0 --no-cabac\n"
" --cqm flat --weightp 0\n"
" - main:\n"
" --no-8x8dct --cqm flat\n"
" No lossless.\n"
+#endif
" - high:\n"
" No lossless.\n"
#endif
" Support for 4:2:0/4:2:2/4:4:4 chroma subsampling.\n" );
else H0(
" - "
-#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420
+#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT <= X264_CSP_I420
#if HAVE_BITDEPTH8
- "baseline,main,high,"
+#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420
+ "baseline,main,"
+#endif
+ "high,"
#endif
#if HAVE_BITDEPTH10
"high10,"
H1( " --input-csp <string> Specify input colorspace format for raw input\n" );
print_csp_names( longhelp );
H1( " --output-csp <string> Specify output colorspace [\"%s\"]\n"
- " - %s\n", output_csp_names[0], stringify_names( buf, output_csp_names ) );
+ " - %s\n",
+#if X264_CHROMA_FORMAT
+ output_csp_names[0],
+#else
+ "i420",
+#endif
+ stringify_names( buf, output_csp_names ) );
H1( " --input-depth <integer> Specify input bit depth for raw input\n" );
H1( " --output-depth <integer> Specify output bit depth\n" );
H1( " --input-range <string> Specify input color range [\"%s\"]\n"
/* force the output csp to what the user specified (or the default) */
param->i_csp = info->csp;
int csp = info->csp & X264_CSP_MASK;
- if( output_csp == X264_CSP_I420 && (csp < X264_CSP_I420 || csp >= X264_CSP_I422) )
+ if( output_csp == X264_CSP_I400 && csp != X264_CSP_I400 )
+ param->i_csp = X264_CSP_I400;
+ else if( output_csp == X264_CSP_I420 && (csp < X264_CSP_I420 || csp >= X264_CSP_I422) )
param->i_csp = X264_CSP_I420;
else if( output_csp == X264_CSP_I422 && (csp < X264_CSP_I422 || csp >= X264_CSP_I444) )
param->i_csp = X264_CSP_I422;
#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 };
+ static const uint8_t output_csp_fix[] = { X264_CSP_I400, X264_CSP_I420, X264_CSP_I422, X264_CSP_I444, X264_CSP_RGB };
#endif
param->i_csp = output_csp = output_csp_fix[output_csp];
break;
#include "x264_config.h"
-#define X264_BUILD 155
+#define X264_BUILD 156
/* Application developers planning to link against a shared library version of
* libx264 from a Microsoft Visual Studio or similar development environment
/* Colorspace type */
#define X264_CSP_MASK 0x00ff /* */
#define X264_CSP_NONE 0x0000 /* Invalid mode */
-#define X264_CSP_I420 0x0001 /* yuv 4:2:0 planar */
-#define X264_CSP_YV12 0x0002 /* yvu 4:2:0 planar */
-#define X264_CSP_NV12 0x0003 /* yuv 4:2:0, with one y plane and one packed u+v */
-#define X264_CSP_NV21 0x0004 /* yuv 4:2:0, with one y plane and one packed v+u */
-#define X264_CSP_I422 0x0005 /* yuv 4:2:2 planar */
-#define X264_CSP_YV16 0x0006 /* yvu 4:2:2 planar */
-#define X264_CSP_NV16 0x0007 /* yuv 4:2:2, with one y plane and one packed u+v */
-#define X264_CSP_YUYV 0x0008 /* yuyv 4:2:2 packed */
-#define X264_CSP_UYVY 0x0009 /* uyvy 4:2:2 packed */
-#define X264_CSP_V210 0x000a /* 10-bit yuv 4:2:2 packed in 32 */
-#define X264_CSP_I444 0x000b /* yuv 4:4:4 planar */
-#define X264_CSP_YV24 0x000c /* yvu 4:4:4 planar */
-#define X264_CSP_BGR 0x000d /* packed bgr 24bits */
-#define X264_CSP_BGRA 0x000e /* packed bgr 32bits */
-#define X264_CSP_RGB 0x000f /* packed rgb 24bits */
-#define X264_CSP_MAX 0x0010 /* end of list */
+#define X264_CSP_I400 0x0001 /* monochrome 4:0:0 */
+#define X264_CSP_I420 0x0002 /* yuv 4:2:0 planar */
+#define X264_CSP_YV12 0x0003 /* yvu 4:2:0 planar */
+#define X264_CSP_NV12 0x0004 /* yuv 4:2:0, with one y plane and one packed u+v */
+#define X264_CSP_NV21 0x0005 /* yuv 4:2:0, with one y plane and one packed v+u */
+#define X264_CSP_I422 0x0006 /* yuv 4:2:2 planar */
+#define X264_CSP_YV16 0x0007 /* yvu 4:2:2 planar */
+#define X264_CSP_NV16 0x0008 /* yuv 4:2:2, with one y plane and one packed u+v */
+#define X264_CSP_YUYV 0x0009 /* yuyv 4:2:2 packed */
+#define X264_CSP_UYVY 0x000a /* uyvy 4:2:2 packed */
+#define X264_CSP_V210 0x000b /* 10-bit yuv 4:2:2 packed in 32 */
+#define X264_CSP_I444 0x000c /* yuv 4:4:4 planar */
+#define X264_CSP_YV24 0x000d /* yvu 4:4:4 planar */
+#define X264_CSP_BGR 0x000e /* packed bgr 24bits */
+#define X264_CSP_BGRA 0x000f /* packed bgr 32bits */
+#define X264_CSP_RGB 0x0010 /* packed rgb 24bits */
+#define X264_CSP_MAX 0x0011 /* end of list */
#define X264_CSP_VFLIP 0x1000 /* the csp is vertically flipped */
#define X264_CSP_HIGH_DEPTH 0x2000 /* the csp has a depth of 16 bits per pixel component */