4:0:0 (monochrome) encoding support
authorEmanuele Ruffaldi <emanuele.ruffaldi@gmail.com>
Sat, 6 Jan 2018 01:34:39 +0000 (02:34 +0100)
committerHenrik Gramner <henrik@gramner.com>
Mon, 6 Aug 2018 21:24:12 +0000 (23:24 +0200)
Virtually zero increase in compression efficiency compared to 4:2:0 with empty
chroma planes. Performance is better though, especially with fast settings.

27 files changed:
common/base.c
common/common.h
common/deblock.c
common/frame.c
common/macroblock.c
common/mc.c
common/mc.h
common/x86/mc-a.asm
common/x86/mc-c.c
configure
encoder/analyse.c
encoder/cabac.c
encoder/cavlc.c
encoder/encoder.c
encoder/macroblock.c
encoder/me.c
encoder/ratecontrol.c
encoder/rdo.c
encoder/set.c
encoder/slicetype.c
filters/video/depth.c
filters/video/resize.c
input/avs.c
input/input.c
input/y4m.c
x264.c
x264.h

index 3befe73..0765482 100644 (file)
@@ -749,6 +749,11 @@ static int param_apply_profile( x264_param_t *param, const char *profile )
         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 )
     {
index b1f83ef..927d6fa 100644 (file)
@@ -86,7 +86,7 @@
 #    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)
 
index 7ec5853..5b63ef3 100644 (file)
@@ -383,6 +383,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
     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;
@@ -420,7 +421,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                 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,\
@@ -429,14 +430,14 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                                          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,\
@@ -463,16 +464,22 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                 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;
@@ -483,16 +490,22 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                 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
@@ -548,7 +561,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                         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] );
                 }
             }
index a783ed2..b5229a1 100644 (file)
@@ -44,29 +44,16 @@ static int align_plane_size( int x, int disalign )
 
 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 )
@@ -119,6 +106,14 @@ 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;
 
@@ -470,7 +465,7 @@ int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
                                          (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 );
index 8b22dbb..bde8fb7 100644 (file)
@@ -48,7 +48,7 @@ static NOINLINE void mb_mc_0xywh( x264_t *h, int x, int y, int width, int height
         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
@@ -87,7 +87,7 @@ static NOINLINE void mb_mc_1xywh( x264_t *h, int x, int y, int width, int height
         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 )
@@ -132,7 +132,7 @@ static NOINLINE void mb_mc_01xywh( x264_t *h, int x, int y, int width, int heigh
         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 )
@@ -531,17 +531,20 @@ void x264_macroblock_thread_init( x264_t *h )
      */
     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;
+        }
     }
 }
 
@@ -1006,7 +1009,7 @@ static void ALWAYS_INLINE macroblock_cache_load( x264_t *h, int mb_x, int mb_y,
             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 );
@@ -1026,7 +1029,7 @@ static void ALWAYS_INLINE macroblock_cache_load( x264_t *h, int mb_x, int mb_y,
             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 );
     }
 
@@ -1643,7 +1646,7 @@ static void ALWAYS_INLINE macroblock_backup_intra( x264_t *h, int mb_x, int mb_y
         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) );
@@ -1661,7 +1664,7 @@ static void ALWAYS_INLINE macroblock_backup_intra( x264_t *h, int mb_x, int mb_y
                 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;
@@ -1695,7 +1698,7 @@ void x264_macroblock_cache_save( x264_t *h )
             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
@@ -1707,7 +1710,7 @@ void x264_macroblock_cache_save( x264_t *h )
             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 );
     }
 
index 4ca69f1..1f515da 100644 (file)
@@ -652,6 +652,7 @@ void x264_mc_init( int cpu, x264_mc_functions_t *pf, int cpu_independent )
 
     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;
index f3d32eb..e11fc42 100644 (file)
@@ -308,6 +308,7 @@ typedef struct
 
     /* 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 */
index e2e99cb..48a201b 100644 (file)
@@ -1515,6 +1515,25 @@ INIT_MMX mmx2
 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 )
 ;-----------------------------------------------------------------------------
index dc89f19..d7143c9 100644 (file)
@@ -159,6 +159,8 @@ void x264_mc_copy_w16_aligned_sse( pixel *, intptr_t, pixel *, intptr_t, int );
 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)
@@ -796,6 +798,7 @@ void x264_mc_init_mmx( int cpu, x264_mc_functions_t *pf )
     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;
index 3063cd7..70fe576 100755 (executable)
--- a/configure
+++ b/configure
@@ -31,7 +31,7 @@ Configuration options:
   --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
@@ -517,8 +517,8 @@ for opt do
             ;;
         --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
             ;;
index e3e51f4..9a74360 100644 (file)
@@ -309,8 +309,8 @@ static void mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int qp )
     /* 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. */
@@ -1035,7 +1035,7 @@ static void intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
     }
 
     /* 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 )
index e3a4a8e..f121449 100644 (file)
@@ -1089,8 +1089,10 @@ void x264_macroblock_write_cabac( x264_t *h, x264_cabac_t *cb )
 {
     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
index 06ad0b9..929ee7d 100644 (file)
@@ -489,7 +489,7 @@ void x264_macroblock_write_cavlc( x264_t *h )
     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;
index 286b112..5cbeb68 100644 (file)
@@ -100,7 +100,7 @@ static void frame_dump( x264_t *h )
         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;
@@ -293,25 +293,29 @@ static void slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal_ref_
     {
         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 );
+                    }
                 }
             }
         }
@@ -475,7 +479,12 @@ static int 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_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;
@@ -493,13 +502,26 @@ static int validate_parameters( x264_t *h, int b_open )
 #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",
@@ -1348,6 +1370,9 @@ static void chroma_dsp_init( x264_t *h )
 
     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;
@@ -1737,17 +1762,9 @@ x264_t *x264_encoder_open( x264_param_t *param )
         (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:
@@ -4253,17 +4270,27 @@ void    x264_encoder_close  ( x264_t *h )
         }
 
         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};
@@ -4310,9 +4337,13 @@ void    x264_encoder_close  ( x264_t *h )
                       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++ )
index 12888ec..8f3111e 100644 (file)
@@ -975,8 +975,10 @@ void x264_macroblock_encode( x264_t *h )
 {
     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 );
 }
 
 /*****************************************************************************
@@ -1126,12 +1128,14 @@ static ALWAYS_INLINE int macroblock_probe_skip_internal( x264_t *h, int b_bidir,
 
 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 );
 }
 
 /****************************************************************************
@@ -1365,12 +1369,14 @@ static ALWAYS_INLINE void macroblock_encode_p8x8_internal( x264_t *h, int i8, in
 
 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 );
 }
 
 /*****************************************************************************
index a388039..3c9f0e4 100644 (file)
@@ -1011,7 +1011,7 @@ static void refine_subpel( x264_t *h, x264_me_t *m, int hpel_iters, int qpel_ite
             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 );\
     }\
@@ -1134,7 +1134,7 @@ static void ALWAYS_INLINE me_refine_bidir( x264_t *h, x264_me_t *m0, x264_me_t *
                             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 );
@@ -1216,7 +1216,7 @@ void x264_me_refine_bidir_rd( x264_t *h, x264_me_t *m0, x264_me_t *m1, int i_wei
             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 ); \
index b7f0ee0..c2f455f 100644 (file)
@@ -278,7 +278,7 @@ static NOINLINE uint32_t ac_energy_mb( x264_t *h, int mb_x, int mb_y, x264_frame
             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 );
@@ -293,7 +293,7 @@ static NOINLINE uint32_t ac_energy_mb( x264_t *h, int mb_x, int mb_y, x264_frame
             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();
index e82aa3c..02b61f9 100644 (file)
@@ -148,10 +148,14 @@ static inline int ssd_plane( x264_t *h, int size, int p, int x, int y )
 
 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 )
@@ -250,10 +254,13 @@ uint64_t x264_rd_cost_part( x264_t *h, int i_lambda2, int i4, int i_pixel )
     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 )
     {
index 6471180..628518a 100644 (file)
@@ -106,7 +106,8 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
     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 )
@@ -115,7 +116,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
         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;
@@ -200,19 +201,11 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
     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 &&
index 3454fb8..cb09b66 100644 (file)
@@ -319,7 +319,7 @@ void x264_weights_analyse( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, int
     }
 
     /* 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;
index 9b96158..a957079 100644 (file)
@@ -51,7 +51,8 @@ typedef struct
 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 ||
index 636115f..dda5db9 100644 (file)
@@ -72,6 +72,7 @@ typedef struct
     /* 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 */
@@ -146,6 +147,7 @@ static int convert_csp_to_pix_fmt( int csp )
         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 */
@@ -202,7 +204,7 @@ static int pick_closest_supported_csp( int csp )
     {
         // 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
@@ -398,9 +400,12 @@ static int check_resizer( resizer_hnd_t *h, cli_pic_t *in )
         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;
@@ -504,6 +509,11 @@ static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x2
                       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 )
     {
@@ -536,7 +546,7 @@ static int get_frame( hnd_t handle, cli_pic_t *output, int frame )
     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 );
index c81a1e3..8520afd 100644 (file)
@@ -190,6 +190,8 @@ fail:
 #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 ))
@@ -200,6 +202,8 @@ fail:
 #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 */
@@ -288,7 +292,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
     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 );
@@ -339,16 +343,17 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
     {
         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 )) )
@@ -356,46 +361,58 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
         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 */
@@ -443,13 +460,15 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
         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
     {
index af7d43d..70c4fa0 100644 (file)
@@ -34,6 +34,7 @@
 #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 },
index c688c2f..5a80af6 100644 (file)
@@ -48,10 +48,12 @@ typedef struct
 
 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;
@@ -59,7 +61,8 @@ static int parse_csp_and_depth( char *csp_name, int *bit_depth )
         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;
diff --git a/x264.c b/x264.c
index c88ed20..fb39288 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -199,6 +199,9 @@ static const char * const pulldown_names[] = { "none", "22", "32", "64", "double
 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
@@ -213,6 +216,7 @@ static const char * const output_csp_names[] =
 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"
@@ -554,8 +558,9 @@ 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_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"
@@ -564,6 +569,7 @@ static void help( x264_param_t *defaults, int longhelp )
         "                                  - main:\n"
         "                                    --no-8x8dct --cqm flat\n"
         "                                    No lossless.\n"
+#endif
         "                                  - high:\n"
         "                                    No lossless.\n"
 #endif
@@ -584,9 +590,12 @@ static void help( x264_param_t *defaults, int longhelp )
         "                                    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,"
@@ -905,7 +914,13 @@ static void help( x264_param_t *defaults, int longhelp )
     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"
@@ -1325,7 +1340,9 @@ static int init_vid_filters( char *sequence, hnd_t *handle, video_info_t *info,
     /* 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;
@@ -1556,7 +1573,7 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
 #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;
diff --git a/x264.h b/x264.h
index 77b6b8a..3e8951f 100644 (file)
--- a/x264.h
+++ b/x264.h
@@ -45,7 +45,7 @@ extern "C" {
 
 #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
@@ -219,22 +219,23 @@ static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 };
 /* 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 */