[x264-devel] [PATCH ]Support 12bit and add ultra calss

xuefeng xuefeng at multicorewareinc.com
Tue Sep 29 11:11:17 CEST 2015


From 42f66a8e7b25865945222447fcaa924a5580669d Mon Sep 17 00:00:00 2001
From: xuefeng <xuefeng at multicorewareinc.com>
Date: Thu, 24 Sep 2015 15:54:17 +0800
Subject: [PATCH] Support 12bit and add ultra calss based on AVC-Ultra
 Specification from Panasonic Corporation, T-REC-H.264-201402-I!!PDF-E.pdf and
 C-AVC Intra specification v1.1 20080404.doc

---
 common/common.c       |  69 +++-
 common/common.h       |   2 +-
 common/macroblock.h   |   6 +
 common/set.h          | 109 ++++++
 configure             |   6 +-
 encoder/analyse.c     |  15 +-
 encoder/encoder.c     | 913 +++++++++++++++++++++++++++++++++++++++++++++++++-
 encoder/ratecontrol.c |   4 +-
 encoder/set.c         |  16 +-
 x264.c                |  37 +-
 x264.h                |   1 +
 11 files changed, 1146 insertions(+), 32 deletions(-)

diff --git a/common/common.c b/common/common.c
index 6999a00..012fbb2 100644
--- a/common/common.c
+++ b/common/common.c
@@ -453,7 +453,7 @@ static int profile_string_to_int( const char *str )
     return -1;
 }
 
-int x264_param_apply_profile( x264_param_t *param, const char *profile )
+static int x264_param_apply_default_profile( x264_param_t *param, const char *profile )
 {
     if( !profile )
         return 0;
@@ -514,6 +514,73 @@ int x264_param_apply_profile( x264_param_t *param, const char *profile )
     return 0;
 }
 
+static int class_string_to_int( const char *str )
+{
+#if BIT_DEPTH == 10
+    if( !strcasecmp( str, "intra-480" ) )
+        return AVCULTRA_CLASS_480;
+    if( !strcasecmp( str, "intra-300" ) )
+        return AVCULTRA_CLASS_300;
+    if( !strcasecmp( str, "intra-200" ) )
+        return AVCULTRA_CLASS_200;
+    if( !strcasecmp( str, "intra-100" ) )
+        return AVCULTRA_CLASS_100;
+    if( !strcasecmp( str, "intra-50" ) )
+        return AVCULTRA_CLASS_50;
+
+    if( !strcasecmp( str, "xavc-class-x25" ) )
+        return XAVC_CLASS_X25;
+    if( !strcasecmp( str, "xavc-class-x35" ) )
+        return XAVC_CLASS_X35;
+    if( !strcasecmp( str, "xavc-class-x50" ) )
+        return XAVC_CLASS_X50;
+#elif BIT_DEPTH == 12
+    if( !strcasecmp( str, "intra-444-220" ) )
+        return AVCULTRA_CLASS_220;
+    if( !strcasecmp( str, "intra-480" ) )
+        return AVCULTRA_CLASS_480;
+    if( !strcasecmp( str, "intra-444-600" ) )
+        return AVCULTRA_CLASS_600;
+#endif
+    return 0;
+}
+
+int x264_param_apply_profile( x264_param_t *param, const char *profiles )
+{
+    if( !profiles )
+        return 0;
+    const char *profile = profiles;
+    // test whether the first param is a param for class ultra or class xavc
+    if( param->i_ex_class > 0)
+    {
+        int csp = param->i_ex_class;
+        param->i_ex_class = class_string_to_int( profile );
+#if BIT_DEPTH == 10
+        if ( AVCULTRA_CLASS_480 == param->i_ex_class && !( 422 == csp ) )
+            param->i_ex_class = 0;
+#elif BIT_DEPTH == 12
+        if ( AVCULTRA_CLASS_480 == param->i_ex_class && !( 444 == csp ) )
+            param->i_ex_class = 0;
+#endif
+        if( param->i_ex_class == 0 )
+        {
+            x264_log( NULL, X264_LOG_ERROR, "invalid constraint class: %s\n", profile );
+#if BIT_DEPTH == 10
+            x264_log( NULL, X264_LOG_ERROR, "%d bits constraint: intra-50, intra-100, intra-200, intra-300, intra-480\n", BIT_DEPTH );
+#elif BIT_DEPTH == 12
+            x264_log( NULL, X264_LOG_ERROR, "%d bits constraint support: intra-444-220, intra-480, intra-444-600 \n", BIT_DEPTH );
+#endif
+            return -1;
+        }
+        profile = profiles + (strlen( profile ) + 1);
+        if( 0 == *profile )
+            return 0;
+    }
+    x264_param_apply_default_profile( param, profile );
+
+    return 0;
+}
+
 static int parse_enum( const char *arg, const char * const *names, int *dst )
 {
     for( int i = 0; names[i]; i++ )
diff --git a/common/common.h b/common/common.h
index 9cda187..e1ccdcc 100644
--- a/common/common.h
+++ b/common/common.h
@@ -109,7 +109,7 @@ do {\
 
 #define NALU_OVERHEAD 5 // startcode + NAL type costs 5 bytes per frame
 #define FILLER_OVERHEAD (NALU_OVERHEAD+1)
-#define SEI_OVERHEAD (NALU_OVERHEAD - (h->param.b_annexb && !h->param.i_avcintra_class && (h->out.i_nal-1)))
+#define SEI_OVERHEAD (NALU_OVERHEAD - (h->param.b_annexb && !( h->param.i_avcintra_class || h->param.i_ex_class ) && (h->out.i_nal-1)))
 
 /****************************************************************************
  * Includes
diff --git a/common/macroblock.h b/common/macroblock.h
index 7974f5a..41fac75 100644
--- a/common/macroblock.h
+++ b/common/macroblock.h
@@ -250,6 +250,12 @@ static const uint8_t i_chroma_qp_table[QP_MAX+1+12*2] =
 {
          0,      0,      0,      0,      0,      0,
          0,      0,      0,      0,      0,      0,
+#if BIT_DEPTH > 11
+   QP(-24), QP(-23), QP(-22), QP(-21), QP(-20), QP(-19),
+#endif
+#if BIT_DEPTH > 10
+   QP(-18), QP(-17), QP(-16), QP(-15), QP(-14), QP(-13),
+#endif
 #if BIT_DEPTH > 9
    QP(-12),QP(-11),QP(-10), QP(-9), QP(-8), QP(-7),
 #endif
diff --git a/common/set.h b/common/set.h
index 0d4f806..489dd80 100644
--- a/common/set.h
+++ b/common/set.h
@@ -37,6 +37,27 @@ enum profile_e
     PROFILE_HIGH444_PREDICTIVE = 244,
 };
 
+enum class_e
+{
+    // avcultra class
+#if BIT_DEPTH == 10
+    AVCULTRA_CLASS_50 = 1,
+    AVCULTRA_CLASS_100,
+    AVCULTRA_CLASS_200,
+    AVCULTRA_CLASS_300,
+    AVCULTRA_CLASS_480,
+#elif BIT_DEPTH == 12
+    AVCULTRA_CLASS_220 = 1,
+    AVCULTRA_CLASS_480,
+    AVCULTRA_CLASS_600,
+#endif
+
+    // xavc class
+    XAVC_CLASS_X25,
+    XAVC_CLASS_X35,
+    XAVC_CLASS_X50,
+};
+
 enum chroma_format_e
 {
     CHROMA_400 = 0,
@@ -257,6 +278,42 @@ static const uint8_t x264_cqm_avci50_4ic[16] =
     40,44,48,60
 };
 
+//2160p25_avci300  //TODO: The temporary quantization matrix
+static const uint8_t x264_cqm_avci300_2160_4ic[16] =
+{
+    16,16,16,16,
+    16,16,16,16,
+    16,16,16,16,
+    16,16,16,16
+};
+
+//2160p25_avci480  //TODO: The temporary quantization matrix
+static const uint8_t x264_cqm_avci480_2160_4ic[16] =
+{
+    16,16,16,16,
+    16,16,16,16,
+    16,16,16,16,
+    16,16,16,16
+};
+
+//2160p25_avci600  //TODO: The temporary quantization matrix
+static const uint8_t x264_cqm_avci600_2160_4ic[16] =
+{
+    16,16,16,16,
+    16,16,16,16,
+    16,16,16,16,
+    16,16,16,16
+};
+
+//1080p25_avci220  //TODO: The temporary quantization matrix
+static const uint8_t x264_cqm_avci220_1080_4ic[16] =
+{
+    16,16,16,16,
+    16,16,16,16,
+    16,16,16,16,
+    16,16,16,16
+};
+
 //  1080i25_avci50,
 static const uint8_t x264_cqm_avci50_1080i_8iy[64] =
 {
@@ -340,6 +397,58 @@ static const uint8_t x264_cqm_avci100_720p_8iy[64] =
     32,32,32,34,34,36,38,42
 };
 
+// 2160p25_avci300,2160p50_avci300  //TODO: The temporary quantization matrix
+static const uint8_t x264_cqm_avci300_2160p_8iy[64] =
+{
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16
+};
+
+// 2160p25_avci480,2160p25_avci480  //TODO: The temporary quantization matrix
+static const uint8_t x264_cqm_avci480_2160p_8iy[64] =
+{
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16
+};
+
+// 2160p25_avci600  //TODO: The temporary quantization matrix
+static const uint8_t x264_cqm_avci600_2160p_8iy[64] =
+{
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16
+};
+
+// 1080p25_avci220  //TODO: The temporary quantization matrix
+static const uint8_t x264_cqm_avci220_1080p_8iy[64] =
+{
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16
+};
+
 int  x264_cqm_init( x264_t *h );
 void x264_cqm_delete( x264_t *h );
 int  x264_cqm_parse_file( x264_t *h, const char *filename );
diff --git a/configure b/configure
index 57a47ac..c905df8 100755
--- a/configure
+++ b/configure
@@ -30,7 +30,7 @@ Configuration options:
   --disable-thread         disable multithreaded encoding
   --enable-win32thread     use win32threads (windows only)
   --disable-interlaced     disable interlaced encoding support
-  --bit-depth=BIT_DEPTH    set output bit depth (8-10) [8]
+  --bit-depth=BIT_DEPTH    set output bit depth (8-12) [8]
   --chroma-format=FORMAT   output chroma format (420, 422, 444, all) [all]
 
 Advanced options:
@@ -481,8 +481,8 @@ for opt do
             ;;
         --bit-depth=*)
             bit_depth="$optarg"
-            if [ "$bit_depth" -lt "8" -o "$bit_depth" -gt "10" ]; then
-                echo "Supplied bit depth must be in range [8,10]."
+            if [ "$bit_depth" -lt "8" -o "$bit_depth" -gt "12" ]; then
+                echo "Supplied bit depth must be in range [8,12]."
                 exit 1
             fi
             bit_depth=`expr $bit_depth + 0`
diff --git a/encoder/analyse.c b/encoder/analyse.c
index b82f647..5a22036 100644
--- a/encoder/analyse.c
+++ b/encoder/analyse.c
@@ -436,7 +436,7 @@ static void x264_mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int qp )
     /* 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. */
     uint64_t pcm_cost = ((uint64_t)X264_PCM_COST*a->i_lambda2 + 128) >> 8;
-    a->i_satd_pcm = !h->param.i_avcintra_class && !h->mb.i_psy_rd && a->i_mbrd && pcm_cost < COST_MAX ? pcm_cost : COST_MAX;
+    a->i_satd_pcm = !h->param.i_avcintra_class && !h->param.i_ex_class && !h->mb.i_psy_rd && a->i_mbrd && pcm_cost < COST_MAX ? pcm_cost : COST_MAX;
 
     a->b_fast_intra = 0;
     a->b_avoid_topright = 0;
@@ -812,7 +812,7 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
 
     /*---------------- Try all mode and calculate their score ---------------*/
     /* Disabled i16x16 for AVC-Intra compat */
-    if( !h->param.i_avcintra_class )
+    if( !( h->param.i_avcintra_class || h->param.i_ex_class ) )
     {
         const int8_t *predict_mode = predict_16x16_mode_available( h->mb.i_neighbour_intra );
 
@@ -3055,10 +3055,13 @@ intra_analysis:
         if( analysis.i_mbrd )
             x264_intra_rd( h, &analysis, COST_MAX );
 
-        i_cost = analysis.i_satd_i16x16;
-        h->mb.i_type = I_16x16;
-        COPY2_IF_LT( i_cost, analysis.i_satd_i4x4, h->mb.i_type, I_4x4 );
-        COPY2_IF_LT( i_cost, analysis.i_satd_i8x8, h->mb.i_type, I_8x8 );
+        if ( !( h->param.i_avcintra_class || h->param.i_ex_class ) )
+        {
+            i_cost = analysis.i_satd_i16x16;
+            h->mb.i_type = I_16x16;
+            COPY2_IF_LT( i_cost, analysis.i_satd_i4x4, h->mb.i_type, I_4x4 );
+            COPY2_IF_LT( i_cost, analysis.i_satd_i8x8, h->mb.i_type, I_8x8 );
+        }
         if( analysis.i_satd_pcm < i_cost )
             h->mb.i_type = I_PCM;
 
diff --git a/encoder/encoder.c b/encoder/encoder.c
index 79997b9..4722c98 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -410,6 +410,885 @@ static void x264_encoder_thread_init( x264_t *h )
 }
 #endif
 
+#if BIT_DEPTH == 10
+static int apply_avcultra_class_50_profile( x264_t *h )
+{
+    if( h->param.nalu_process )
+    {
+        x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    if( !h->param.b_repeat_headers )
+    {
+        x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    h->param.b_cabac = 1;
+    h->param.i_keyint_max = 1;
+    h->param.b_deblocking_filter = 0;
+    h->param.i_nal_hrd = X264_NAL_HRD_CBR;
+    h->param.i_slice_count = 10;
+    h->param.analyse.b_transform_8x8 = 1;
+    h->param.analyse.intra = X264_ANALYSE_I8x8;
+    h->param.rc.i_rc_method = X264_RC_ABR;
+
+    // sps set
+    h->param.vui.i_sar_width = 4;
+    h->param.vui.i_sar_height = 3;
+    h->param.vui.i_overscan = 2;
+    h->param.vui.i_vidformat = 0;
+    h->param.vui.b_fullrange = 0;
+    h->param.vui.i_colorprim = 1;
+    h->param.vui.i_transfer = 1;
+    h->param.vui.i_colmatrix = 1;
+    h->param.b_pic_struct = 0;
+
+    // pps set
+    h->param.i_frame_reference = 1;
+    h->param.analyse.i_weighted_pred = 0;
+    h->param.analyse.i_chroma_qp_offset = 4;
+    h->param.b_stitchable = 1;
+
+    if( h->param.i_width == 960 && h->param.i_height == 720 )
+    {
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 53276)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 54067)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 26638)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 27033)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 27033)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 21314)) ||
+        (h->param.i_ex_class = 0);
+
+        h->param.i_level_idc = 32;
+    }
+    else if( h->param.i_width == 1440 && h->param.i_height == 1080 )
+    {
+        if( (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 107044)) ||
+            (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 108544)) )
+        {
+            h->param.i_level_idc = 42;
+        }
+        else if( (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 1 && (h->param.rc.i_bitrate = 107044)) ||
+                 (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 1 && (h->param.rc.i_bitrate = 108544)) ||
+                 (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 53522)) ||
+                 (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 54272)) ||
+                 (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 54272)) ||
+                 (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 42800)) )
+        {
+            h->param.i_level_idc = 40;
+        }
+        else
+        {
+            h->param.i_ex_class = 0;
+        }
+    }
+    else
+        h->param.i_ex_class = 0;
+
+    if( !h->param.i_ex_class )
+    {
+        x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid or FPS %d invalid or Interlaced %c invalid for AVC-Ultra 50 Class\n",
+                  h->param.i_width, h->param.i_height, h->param.i_fps_num, h->param.b_interlaced ? 'I' : 'P' );
+        return -1;
+    }
+
+    memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof( h->param.cqm_4iy ) );
+    memcpy( h->param.cqm_4ic, x264_cqm_avci50_4ic, sizeof( h->param.cqm_4ic ) );
+    if( PARAM_INTERLACED == 0 )
+    {
+        memcpy( h->param.cqm_8iy, x264_cqm_avci50_p_8iy, sizeof( h->param.cqm_8iy ) );
+    }
+    else
+    {
+        memcpy( h->param.cqm_8iy, x264_cqm_avci50_1080i_8iy, sizeof( h->param.cqm_8iy ) );
+    }
+
+    h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
+    h->param.rc.i_vbv_buffer_size = h->param.rc.i_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+
+    return 0;
+}
+
+static int apply_avcultra_class_100_profile( x264_t *h )
+{
+    if( h->param.nalu_process )
+    {
+        x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    if( !h->param.b_repeat_headers )
+    {
+        x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    h->param.b_cabac = 0;
+    h->param.i_keyint_max = 1;
+    h->param.b_deblocking_filter = 0;
+    h->param.i_slice_count = 10;
+    h->param.analyse.b_transform_8x8 = 1;
+    h->param.analyse.intra = X264_ANALYSE_I8x8;
+
+    // sps set
+    h->param.vui.i_sar_width = 1;
+    h->param.vui.i_sar_height = 1;
+    h->param.vui.i_overscan = 2;
+    h->param.vui.i_vidformat = 0;
+    h->param.vui.b_fullrange = 0;
+    h->param.vui.i_colorprim = 1;
+    h->param.vui.i_transfer = 1;
+    h->param.vui.i_colmatrix = 1;
+    h->param.b_pic_struct = 0;
+
+    // pps set
+    h->param.i_frame_reference = 1;
+    h->param.analyse.i_weighted_pred = 0;
+    h->param.b_stitchable = 1;
+
+    if( h->param.i_width == 1280 && h->param.i_height == 720 )
+    {
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 110726)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 111616)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 55363)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 55800)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 55800)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 44298)) ||
+        (h->param.i_ex_class = 0);
+
+        h->param.i_level_idc = 41;
+        h->param.i_nal_hrd = X264_NAL_HRD_CBR;
+        h->param.analyse.i_chroma_qp_offset = 4;
+    }
+    else if( h->param.i_width == 1920 && h->param.i_height == 1080 )
+    {
+        if( (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 221944)) ||
+            (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 223641)) )
+        {
+            h->param.i_level_idc = 42;
+        }
+        else if( (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 1 && (h->param.rc.i_bitrate = 221944)) ||
+                 (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 1 && (h->param.rc.i_bitrate = 223641)) ||
+                 (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 110972)) ||
+                 (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 111820)) ||
+                 (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 111820)) ||
+                 (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 88700)) )
+        {
+            h->param.i_level_idc = 41;
+        }
+        else
+        {
+            h->param.i_ex_class = 0;
+        }
+
+        h->param.i_nal_hrd = X264_NAL_HRD_CBR;
+        h->param.analyse.i_chroma_qp_offset = 3;
+    }
+    else if( h->param.i_width == 2048 && h->param.i_height == 1080 )
+    {
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 213000) && (h->param.rc.i_vbv_max_bitrate = 232000)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 215000) && (h->param.rc.i_vbv_max_bitrate = 235000)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 106000) && (h->param.rc.i_vbv_max_bitrate = 116000)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 107000) && (h->param.rc.i_vbv_max_bitrate = 117000)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 107000) && (h->param.rc.i_vbv_max_bitrate = 117000)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 90000) && (h->param.rc.i_vbv_max_bitrate = 98000)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 85000) && (h->param.rc.i_vbv_max_bitrate = 93000)) ||
+        (h->param.i_ex_class = 0);
+
+        h->param.i_level_idc = 42;
+        h->param.i_nal_hrd = X264_NAL_HRD_VBR;
+        h->param.i_slice_count = 8;
+        h->param.analyse.i_chroma_qp_offset = 3;
+    }
+    else
+        h->param.i_ex_class = 0;
+
+    if( !h->param.i_ex_class )
+    {
+        x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid or FPS %d invalid or Interlaced %c invalid for AVC-Ultra 100 Class\n",
+                  h->param.i_width, h->param.i_height, h->param.i_fps_num, h->param.b_interlaced ? 'I' : 'P' );
+        return -1;
+    }
+
+    memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof( h->param.cqm_4iy ) );
+    if( h->param.i_height == 720 )
+    {
+        memcpy( h->param.cqm_4ic, x264_cqm_avci100_720p_4ic, sizeof( h->param.cqm_4ic ) );
+        memcpy( h->param.cqm_8iy, x264_cqm_avci100_720p_8iy, sizeof( h->param.cqm_8iy ) );
+    }
+    else
+    {
+        memcpy( h->param.cqm_4ic, x264_cqm_avci100_1080_4ic, sizeof( h->param.cqm_4ic ) );
+        if( PARAM_INTERLACED == 0 )
+        {
+            memcpy( h->param.cqm_8iy, x264_cqm_avci100_1080p_8iy, sizeof( h->param.cqm_8iy ) );
+        }
+        else
+        {
+            memcpy( h->param.cqm_8iy, x264_cqm_avci100_1080i_8iy, sizeof( h->param.cqm_8iy ) );
+        }
+    }
+
+    if( X264_NAL_HRD_CBR == h->param.i_nal_hrd )
+    {
+        h->param.rc.i_rc_method = X264_RC_ABR;
+        h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
+        h->param.rc.i_vbv_buffer_size = h->param.rc.i_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+    }
+    else
+    {
+        h->param.rc.i_rc_method = X264_RC_ABR;
+        h->param.rc.i_vbv_buffer_size = h->param.rc.i_vbv_max_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+    }
+
+    return 0;
+}
+
+static int apply_avcultra_class_200_profile( x264_t *h )
+{
+    if( h->param.nalu_process )
+    {
+        x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    if( !h->param.b_repeat_headers )
+    {
+        x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    h->param.b_cabac = 0;
+    h->param.i_keyint_max = 1;
+    h->param.b_deblocking_filter = 0;
+    h->param.i_slice_count = 10;
+    h->param.analyse.b_transform_8x8 = 1;
+    h->param.analyse.intra = X264_ANALYSE_I8x8;
+
+    // sps set
+    h->param.vui.i_sar_width = 1;
+    h->param.vui.i_sar_height = 1;
+    h->param.vui.i_overscan = 2;
+    h->param.vui.i_vidformat = 0;
+    h->param.vui.b_fullrange = 0;
+    h->param.vui.i_colorprim = 1;
+    h->param.vui.i_transfer = 1;
+    h->param.vui.i_colmatrix = 1;
+    h->param.b_pic_struct = 0;
+
+    // pps set
+    h->param.i_frame_reference = 1;
+    h->param.analyse.i_weighted_pred = 0;
+    h->param.b_stitchable = 1;
+
+    if( h->param.i_width == 1280 && h->param.i_height == 720 )
+    {
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 90364)) ||
+        (h->param.i_fps_num == 23980 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 90364)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 112936)) ||
+        (h->param.i_fps_num == 29970 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 112936)) ||
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 225873)) ||
+        (h->param.i_fps_num == 59940 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 225873)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 113356)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 113356)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 226713)) ||
+        (h->param.i_ex_class = 0);
+
+        h->param.i_level_idc = 41;
+        h->param.i_nal_hrd = X264_NAL_HRD_CBR;
+        h->param.analyse.i_chroma_qp_offset = 4;
+    }
+    else if( h->param.i_width == 1920 && h->param.i_height == 1080 )
+    {
+        if( (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 451700)) ||
+            (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 453200)) )
+        {
+            h->param.i_level_idc = 50;
+        }
+        else if( (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 1 && (h->param.rc.i_bitrate = 451700)) ||
+                 (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 1 && (h->param.rc.i_bitrate = 453200)) ||
+                 (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 225854)) ||
+                 (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 226600)) ||
+                 (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 226600)) ||
+                 (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 180713)) )
+        {
+            h->param.i_level_idc = 41;
+        }
+        else
+        {
+            h->param.i_ex_class = 0;
+        }
+
+        h->param.i_nal_hrd = X264_NAL_HRD_CBR;
+        h->param.analyse.i_chroma_qp_offset = 3;
+    }
+    else if( h->param.i_width == 2048 && h->param.i_height == 1080 )
+    {
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 220000) && (h->param.rc.i_vbv_max_bitrate = 240000)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 220000) && (h->param.rc.i_vbv_max_bitrate = 240000)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 110000) && (h->param.rc.i_vbv_max_bitrate = 120000)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 110000) && (h->param.rc.i_vbv_max_bitrate = 120000)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 110000) && (h->param.rc.i_vbv_max_bitrate = 120000)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 90000) && (h->param.rc.i_vbv_max_bitrate = 98000)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 90000) && (h->param.rc.i_vbv_max_bitrate = 98000)) ||
+        (h->param.i_ex_class = 0);
+
+        h->param.i_level_idc = 50;
+        h->param.i_nal_hrd = X264_NAL_HRD_VBR;
+        h->param.i_slice_count = 8;
+        h->param.analyse.i_chroma_qp_offset = 3;
+    }
+    else
+        h->param.i_ex_class = 0;
+
+    if( !h->param.i_ex_class )
+    {
+        x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid or FPS %d invalid for AVC-Ultra 200 Class\n",
+                  h->param.i_width, h->param.i_height, h->param.i_fps_num );
+        return -1;
+    }
+
+    memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof( h->param.cqm_4iy ) );
+    memcpy( h->param.cqm_4ic, x264_cqm_avci100_1080_4ic, sizeof( h->param.cqm_4ic ) );
+    if( PARAM_INTERLACED == 0 )
+    {
+        memcpy( h->param.cqm_8iy, x264_cqm_avci100_1080p_8iy, sizeof( h->param.cqm_8iy ) );
+    }
+    else
+    {
+        memcpy( h->param.cqm_8iy, x264_cqm_avci100_1080i_8iy, sizeof( h->param.cqm_8iy ) );
+    }
+
+    if( X264_NAL_HRD_CBR == h->param.i_nal_hrd )
+    {
+        h->param.rc.i_rc_method = X264_RC_ABR;
+        h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
+        h->param.rc.i_vbv_buffer_size = h->param.rc.i_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+    }
+    else
+    {
+        h->param.rc.i_rc_method = X264_RC_ABR;
+        h->param.rc.i_vbv_buffer_size = h->param.rc.i_vbv_max_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+    }
+
+    return 0;
+}
+
+static int apply_avcultra_class_300_profile( x264_t *h )
+{
+    if( h->param.nalu_process )
+    {
+        x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    if( !h->param.b_repeat_headers )
+    {
+        x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    h->param.b_cabac = 0;
+    h->param.i_nal_hrd = X264_NAL_HRD_VBR;
+    h->param.rc.i_rc_method = X264_RC_ABR;
+    h->param.i_level_idc = 52;
+    h->param.i_keyint_max = 1;
+    h->param.b_deblocking_filter = 0;
+    h->param.i_slice_count = 16;
+    h->param.analyse.b_transform_8x8 = 1;
+    h->param.analyse.intra = X264_ANALYSE_I8x8;
+
+    // sps set
+    h->param.vui.i_sar_width = 1;
+    h->param.vui.i_sar_height = 1;
+    h->param.vui.i_overscan = 2;
+    h->param.vui.i_vidformat = 0;
+    h->param.vui.b_fullrange = 0;
+    h->param.vui.i_colorprim = 1;
+    h->param.vui.i_transfer = 1;
+    h->param.vui.i_colmatrix = 1;
+    h->param.b_pic_struct = 0;
+
+    // pps set
+    h->param.i_frame_reference = 1;
+    h->param.analyse.i_weighted_pred = 0;
+    h->param.b_stitchable = 1;
+    h->param.analyse.i_chroma_qp_offset = 3;
+
+    if( h->param.i_width == 3840 && h->param.i_height == 2160 )
+    {
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 576000) && (h->param.rc.i_vbv_max_bitrate = 627000)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 480000) && (h->param.rc.i_vbv_max_bitrate = 523000)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 288000) && (h->param.rc.i_vbv_max_bitrate = 313920)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 240000) && (h->param.rc.i_vbv_max_bitrate = 261600)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 240000) && (h->param.rc.i_vbv_max_bitrate = 261600)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 230000) && (h->param.rc.i_vbv_max_bitrate = 251000)) ||
+        (h->param.i_ex_class = 0);
+    }
+    else if( h->param.i_width == 4096 && h->param.i_height == 2160 )
+    {
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 576000) && (h->param.rc.i_vbv_max_bitrate = 627000)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 480000) && (h->param.rc.i_vbv_max_bitrate = 523000)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 288000) && (h->param.rc.i_vbv_max_bitrate = 313920)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 240000) && (h->param.rc.i_vbv_max_bitrate = 261600)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 240000) && (h->param.rc.i_vbv_max_bitrate = 261600)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 230000) && (h->param.rc.i_vbv_max_bitrate = 251000)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 230000) && (h->param.rc.i_vbv_max_bitrate = 251000)) ||
+        (h->param.i_ex_class = 0);
+    }
+    else
+        h->param.i_ex_class = 0;
+
+    if( !h->param.i_ex_class )
+    {
+        x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid or FPS %d invalid for AVC-Ultra 300 Class\n",
+                  h->param.i_width, h->param.i_height, h->param.i_fps_num );
+        return -1;
+    }
+
+    memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof( h->param.cqm_4iy ) );
+    memcpy( h->param.cqm_4ic, x264_cqm_avci300_2160_4ic, sizeof( h->param.cqm_4ic ) );
+    memcpy( h->param.cqm_8iy, x264_cqm_avci300_2160p_8iy, sizeof( h->param.cqm_8iy ) );
+
+    h->param.rc.i_vbv_buffer_size = h->param.rc.i_vbv_max_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+
+    return 0;
+}
+
+static int apply_avcultra_class_480_profile( x264_t *h )
+{
+    if( h->param.nalu_process )
+    {
+        x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    if( !h->param.b_repeat_headers )
+    {
+        x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    int i_csp = h->param.i_csp & X264_CSP_MASK;
+    if( i_csp != X264_CSP_I422)
+    {
+        x264_log( NULL, X264_LOG_ERROR, "10 bits intra-480 need csp i422\n" );
+        return -1;
+    }
+
+    h->param.i_nal_hrd = X264_NAL_HRD_VBR;
+    h->param.rc.i_rc_method = X264_RC_ABR;
+    h->param.i_level_idc = 52;
+    h->param.b_cabac = 0;
+    h->param.i_keyint_max = 1;
+    h->param.b_deblocking_filter = 0;
+    h->param.i_slice_count = 16;
+    h->param.analyse.b_transform_8x8 = 1;
+    h->param.analyse.intra = X264_ANALYSE_I8x8;
+
+    // sps set
+    h->param.vui.i_sar_width = 1;
+    h->param.vui.i_sar_height = 1;
+    h->param.vui.i_overscan = 2;
+    h->param.vui.i_vidformat = 0;
+    h->param.vui.b_fullrange = 0;
+    h->param.vui.i_colorprim = 1;
+    h->param.vui.i_transfer = 1;
+    h->param.vui.i_colmatrix = 1;
+    h->param.b_pic_struct = 0;
+
+    // pps set
+    h->param.i_frame_reference = 1;
+    h->param.analyse.i_weighted_pred = 0;
+    h->param.b_stitchable = 1;
+    h->param.analyse.i_chroma_qp_offset = 3;
+
+    if( h->param.i_width == 3840 && h->param.i_height == 2160 )
+    {
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 576000) && (h->param.rc.i_vbv_max_bitrate = 627000)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 480000) && (h->param.rc.i_vbv_max_bitrate = 523000)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 288000) && (h->param.rc.i_vbv_max_bitrate = 313920)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 240000) && (h->param.rc.i_vbv_max_bitrate = 261600)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 240000) && (h->param.rc.i_vbv_max_bitrate = 261600)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 230000) && (h->param.rc.i_vbv_max_bitrate = 251000)) ||
+        (h->param.i_ex_class = 0);
+    }
+    else if( h->param.i_width == 4096 && h->param.i_height == 2160 )
+    {
+        (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 576000) && (h->param.rc.i_vbv_max_bitrate = 627000)) ||
+        (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 480000) && (h->param.rc.i_vbv_max_bitrate = 523000)) ||
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 288000) && (h->param.rc.i_vbv_max_bitrate = 313920)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 240000) && (h->param.rc.i_vbv_max_bitrate = 261600)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 240000) && (h->param.rc.i_vbv_max_bitrate = 261600)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 230000) && (h->param.rc.i_vbv_max_bitrate = 251000)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 230000) && (h->param.rc.i_vbv_max_bitrate = 251000)) ||
+        (h->param.i_ex_class = 0);
+    }
+    else
+        h->param.i_ex_class = 0;
+
+    if( !h->param.i_ex_class )
+    {
+        x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid or FPS %d invalid for AVC-Ultra 480 Class\n",
+                  h->param.i_width, h->param.i_height, h->param.i_fps_num );
+        return -1;
+    }
+
+    memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof( h->param.cqm_4iy ) );
+    memcpy( h->param.cqm_4ic, x264_cqm_avci480_2160_4ic, sizeof( h->param.cqm_4ic ) );
+    memcpy( h->param.cqm_8iy, x264_cqm_avci480_2160p_8iy, sizeof( h->param.cqm_8iy ) );
+
+    h->param.rc.i_vbv_buffer_size = h->param.rc.i_vbv_max_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+
+    return 0;
+}
+
+#elif BIT_DEPTH == 12
+static int apply_avcultra_class_220_profile( x264_t *h )
+{
+    if( h->param.nalu_process )
+    {
+        x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    if( !h->param.b_repeat_headers )
+    {
+        x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    h->param.i_nal_hrd = X264_NAL_HRD_VBR;
+    h->param.rc.i_rc_method = X264_RC_ABR;
+    h->param.b_cabac = 0;
+    h->param.i_keyint_max = 1;
+    h->param.b_deblocking_filter = 0;
+    h->param.i_slice_count = 8;
+    h->param.analyse.b_transform_8x8 = 1;
+    h->param.analyse.intra = X264_ANALYSE_I8x8;
+
+    // sps set
+    h->param.vui.i_sar_width = 1;
+    h->param.vui.i_sar_height = 1;
+    h->param.vui.i_overscan = 2;
+    h->param.vui.i_vidformat = 0;
+    h->param.vui.b_fullrange = 0;
+    h->param.vui.i_colorprim = 1;
+    h->param.vui.i_transfer = 1;
+    h->param.vui.i_colmatrix = 1;
+    h->param.b_pic_struct = 0;
+
+    // pps set
+    h->param.i_frame_reference = 1;
+    h->param.analyse.i_weighted_pred = 0;
+    h->param.analyse.i_chroma_qp_offset = 3;
+    h->param.b_stitchable = 1;
+
+
+    if( h->param.i_width == 1920 && h->param.i_height == 1080 )
+    {
+        if( (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 439676) && (h->param.rc.i_vbv_max_bitrate = 479980)) ||
+            (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 367018) && (h->param.rc.i_vbv_max_bitrate = 400384)) )
+        {
+            h->param.i_level_idc = 50;
+        }
+        else if( (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 219990) && (h->param.rc.i_vbv_max_bitrate = 239990)) ||
+                 (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 219990) && (h->param.rc.i_vbv_max_bitrate = 200192)) ||
+                 (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 219990) && (h->param.rc.i_vbv_max_bitrate = 200192)) ||
+                 (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 176348) && (h->param.rc.i_vbv_max_bitrate = 192024)) )
+        {
+            h->param.i_level_idc = 41;
+        }
+        else
+        {
+            h->param.i_ex_class = 0;
+        }
+    }
+    else if( h->param.i_width == 2048 && h->param.i_height == 1080 )
+    {
+        if( (h->param.i_fps_num == 60000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 439981) && (h->param.rc.i_vbv_max_bitrate = 479980)) ||
+            (h->param.i_fps_num == 50000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 367018) && (h->param.rc.i_vbv_max_bitrate = 400384)) )
+        {
+            h->param.i_level_idc = 50;
+        }
+        else if( (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 219990) && (h->param.rc.i_vbv_max_bitrate = 239990)) ||
+                 (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 183509) && (h->param.rc.i_vbv_max_bitrate = 200192)) ||
+                 (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 183509) && (h->param.rc.i_vbv_max_bitrate = 200192)) ||
+                 (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 176495) && (h->param.rc.i_vbv_max_bitrate = 192184)) ||
+                 (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 176348) && (h->param.rc.i_vbv_max_bitrate = 192024)) )
+        {
+            h->param.i_level_idc = 42;
+        }
+        else
+        {
+            h->param.i_ex_class = 0;
+        }
+    }
+    else
+        h->param.i_ex_class = 0;
+
+    if( !h->param.i_ex_class )
+    {
+        x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid or FPS %d invalid for AVC-Ultra 220 Class\n",
+                  h->param.i_width, h->param.i_height, h->param.i_fps_num );
+        return -1;
+    }
+
+    memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof( h->param.cqm_4iy ) );
+    memcpy( h->param.cqm_4ic, x264_cqm_avci220_1080_4ic, sizeof( h->param.cqm_4ic ) );
+    memcpy( h->param.cqm_8iy, x264_cqm_avci220_1080p_8iy, sizeof( h->param.cqm_8iy ) );
+
+    h->param.rc.i_vbv_buffer_size = h->param.rc.i_vbv_max_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+
+    return 0;
+}
+static int apply_avcultra_class_480_profile( x264_t *h )
+{
+    if( h->param.nalu_process )
+    {
+        x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    if( !h->param.b_repeat_headers )
+    {
+        x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    int i_csp = h->param.i_csp & X264_CSP_MASK;
+    if( i_csp != X264_CSP_I444 )
+    {
+        x264_log( NULL, X264_LOG_ERROR, "12 bits intra-480 need csp i444\n" );
+        return -1;
+    }
+
+    h->param.i_nal_hrd = X264_NAL_HRD_VBR;
+    h->param.rc.i_rc_method = X264_RC_ABR;
+    h->param.i_level_idc = 52;
+    h->param.b_cabac = 0;
+    h->param.i_keyint_max = 1;
+    h->param.b_deblocking_filter = 0;
+    h->param.i_slice_count = 16;
+    h->param.analyse.b_transform_8x8 = 1;
+    h->param.analyse.intra = X264_ANALYSE_I8x8;
+
+    // sps set
+    h->param.vui.i_sar_width = 1;
+    h->param.vui.i_sar_height = 1;
+    h->param.vui.i_overscan = 2;
+    h->param.vui.i_vidformat = 0;
+    h->param.vui.b_fullrange = 0;
+    h->param.vui.i_colorprim = 1;
+    h->param.vui.i_transfer = 1;
+    h->param.vui.i_colmatrix = 1;
+    h->param.b_pic_struct = 0;
+
+    // pps set
+    h->param.i_frame_reference = 1;
+    h->param.analyse.i_weighted_pred = 0;
+    h->param.analyse.i_chroma_qp_offset = 3;
+    h->param.b_stitchable = 1;
+
+    if( h->param.i_width == 3840 && h->param.i_height == 2160 )
+    {
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 439898) && (h->param.rc.i_vbv_max_bitrate = 479489)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 366948) && (h->param.rc.i_vbv_max_bitrate = 399974)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 366948) && (h->param.rc.i_vbv_max_bitrate = 399974)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 352112) && (h->param.rc.i_vbv_max_bitrate = 383655)) ||
+        (h->param.i_ex_class = 0);
+    }
+    else if( h->param.i_width == 4096 && h->param.i_height == 2160 )
+    {
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 439898) && (h->param.rc.i_vbv_max_bitrate = 479489)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 366948) && (h->param.rc.i_vbv_max_bitrate = 399974)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 366948) && (h->param.rc.i_vbv_max_bitrate = 399974)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 352405) && (h->param.rc.i_vbv_max_bitrate = 383975)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 352112) && (h->param.rc.i_vbv_max_bitrate = 383655)) ||
+        (h->param.i_ex_class = 0);
+    }
+    else
+        h->param.i_ex_class = 0;
+
+    if( !h->param.i_ex_class )
+    {
+        x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid or FPS %d invalid for AVC-Ultra 480 Class\n",
+                  h->param.i_width, h->param.i_height, h->param.i_fps_num );
+        return -1;
+    }
+
+    memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof( h->param.cqm_4iy ) );
+    memcpy( h->param.cqm_4ic, x264_cqm_avci480_2160_4ic, sizeof( h->param.cqm_4ic ) );
+    memcpy( h->param.cqm_8iy, x264_cqm_avci480_2160p_8iy, sizeof( h->param.cqm_8iy ) );
+
+    h->param.rc.i_vbv_buffer_size = h->param.rc.i_vbv_max_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+
+    return 0;
+}
+static int apply_avcultra_class_600_profile( x264_t *h )
+{
+    if( h->param.nalu_process )
+    {
+        x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    if( !h->param.b_repeat_headers )
+    {
+        x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
+        h->param.i_ex_class = 0;
+        return -1;
+    }
+
+    h->param.i_nal_hrd = X264_NAL_HRD_VBR;
+    h->param.rc.i_rc_method = X264_RC_ABR;
+    h->param.i_level_idc = 52;
+    h->param.b_cabac = 0;
+    h->param.i_keyint_max = 1;
+    h->param.b_deblocking_filter = 0;
+    h->param.i_slice_count = 16;
+    h->param.analyse.b_transform_8x8 = 1;
+    h->param.analyse.intra = X264_ANALYSE_I8x8;
+
+    // sps set
+    h->param.vui.i_sar_width = 1;
+    h->param.vui.i_sar_height = 1;
+    h->param.vui.i_overscan = 2;
+    h->param.vui.i_vidformat = 0;
+    h->param.vui.b_fullrange = 0;
+    h->param.vui.i_colorprim = 1;
+    h->param.vui.i_transfer = 1;
+    h->param.vui.i_colmatrix = 1;
+    h->param.b_pic_struct = 0;
+
+    // pps set
+    h->param.i_frame_reference = 1;
+    h->param.analyse.i_weighted_pred = 0;
+    h->param.analyse.i_chroma_qp_offset = 3;
+    h->param.b_stitchable = 1;
+
+    if( h->param.i_width == 3840 && h->param.i_height == 2160 )
+    {
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 599933) && (h->param.rc.i_vbv_max_bitrate = 653927)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 500444) && (h->param.rc.i_vbv_max_bitrate = 545484)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 500444) && (h->param.rc.i_vbv_max_bitrate = 545484)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 480210) && (h->param.rc.i_vbv_max_bitrate = 523229)) ||
+        (h->param.i_ex_class = 0);
+    }
+    else if( h->param.i_width == 4096 && h->param.i_height == 2160 )
+    {
+        (h->param.i_fps_num == 30000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 599933) && (h->param.rc.i_vbv_max_bitrate = 653927)) ||
+        (h->param.i_fps_num == 25000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 500444) && (h->param.rc.i_vbv_max_bitrate = 545484)) ||
+        (h->param.i_fps_num == 25    && h->param.i_fps_den == 1    && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 500444) && (h->param.rc.i_vbv_max_bitrate = 545484)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1000 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 480000) && (h->param.rc.i_vbv_max_bitrate = 523229)) ||
+        (h->param.i_fps_num == 24000 && h->param.i_fps_den == 1001 && PARAM_INTERLACED == 0 && (h->param.rc.i_bitrate = 480610) && (h->param.rc.i_vbv_max_bitrate = 523665)) ||
+        (h->param.i_ex_class = 0);
+    }
+    else
+        h->param.i_ex_class = 0;
+
+    if( !h->param.i_ex_class )
+    {
+        x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid or FPS %d invalid for AVC-Ultra 600 Class\n",
+                  h->param.i_width, h->param.i_height, h->param.i_fps_num );
+        return -1;
+    }
+
+    memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof( h->param.cqm_4iy ) );
+    memcpy( h->param.cqm_4ic, x264_cqm_avci600_2160_4ic, sizeof( h->param.cqm_4ic ) );
+    memcpy( h->param.cqm_8iy, x264_cqm_avci600_2160p_8iy, sizeof( h->param.cqm_8iy ) );
+
+    h->param.rc.i_vbv_buffer_size = h->param.rc.i_vbv_max_bitrate * h->param.i_fps_den / h->param.i_fps_num;
+
+    return 0;
+}
+#endif
+
+static int x264_param_apply_class_profile( x264_t *h )
+{
+    if( !h->param.i_ex_class )
+    {
+        return -1;
+    }
+
+    if( BIT_DEPTH < 10 )
+    {
+        x264_log( h, X264_LOG_ERROR, "%2d-bit AVC-Intra is not widely compatible\n", BIT_DEPTH );
+        x264_log( h, X264_LOG_ERROR, "HIGH_BIT_DEPTH is required to encode AVC-Intra\n" );
+        return -1;
+    }
+
+    switch( h->param.i_ex_class )
+    {
+#if BIT_DEPTH == 10
+    case AVCULTRA_CLASS_50:
+        if(apply_avcultra_class_50_profile( h ))
+            return -1;
+        break;
+    case AVCULTRA_CLASS_100:
+        if(apply_avcultra_class_100_profile( h ))
+            return -1;
+        break;
+    case AVCULTRA_CLASS_200:
+        if(apply_avcultra_class_200_profile( h ))
+            return -1;
+        break;
+    case AVCULTRA_CLASS_300:
+        if(apply_avcultra_class_300_profile( h ))
+            return -1;
+        break;
+    case AVCULTRA_CLASS_480:
+        if(apply_avcultra_class_480_profile( h ))
+            return -1;
+        break;
+
+    case XAVC_CLASS_X25:
+        // add the constriction for class p25
+        break;
+    case XAVC_CLASS_X35:
+        // add the constriction for class p35
+        break;
+    case XAVC_CLASS_X50:
+        // add the constriction for class p50
+        break;
+#elif BIT_DEPTH == 12
+    case AVCULTRA_CLASS_220:
+        if( apply_avcultra_class_220_profile( h ) )
+            return -1;
+        break;
+    case AVCULTRA_CLASS_480:
+        if( apply_avcultra_class_480_profile( h ) )
+            return -1;
+        break;
+    case AVCULTRA_CLASS_600:
+        if( apply_avcultra_class_600_profile( h ) )
+            return -1;
+        break;
+#endif
+    default:
+        x264_log( h, X264_LOG_ERROR, "Invalid AVC-Ultra class\n" );
+        return -1;
+    }
+    return 0;
+}
+
 /****************************************************************************
  *
  ****************************************************************************
@@ -825,6 +1704,12 @@ static int x264_validate_parameters( x264_t *h, int b_open )
         h->param.rc.i_qp_min = X264_MAX( h->param.rc.i_qp_min, QP_BD_OFFSET + 1 );
     }
 
+    if( h->param.i_ex_class )
+    {
+        if( x264_param_apply_class_profile( h ) )
+            return -1;
+    }
+
     h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, -QP_BD_OFFSET, 51 );
     h->param.rc.f_rf_constant_max = x264_clip3f( h->param.rc.f_rf_constant_max, -QP_BD_OFFSET, 51 );
     h->param.rc.i_qp_constant = x264_clip3( h->param.rc.i_qp_constant, 0, QP_MAX );
@@ -1124,14 +2009,14 @@ static int x264_validate_parameters( x264_t *h, int b_open )
     h->mb.i_psy_trellis = h->param.analyse.i_trellis ? FIX8( h->param.analyse.f_psy_trellis / 4 ) : 0;
     h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_chroma_qp_offset, -32, 32);
     /* In 4:4:4 mode, chroma gets twice as much resolution, so we can halve its quality. */
-    if( b_open && i_csp >= X264_CSP_I444 && i_csp < X264_CSP_BGR && h->param.analyse.b_psy )
+    if( b_open && i_csp >= X264_CSP_I444 && i_csp < X264_CSP_BGR && h->param.analyse.b_psy && h->param.i_ex_class <= 0 )
         h->param.analyse.i_chroma_qp_offset += 6;
     /* Psy RDO increases overall quantizers to improve the quality of luma--this indirectly hurts chroma quality */
     /* so we lower the chroma QP offset to compensate */
-    if( b_open && h->mb.i_psy_rd && !h->param.i_avcintra_class )
+    if( b_open && h->mb.i_psy_rd && !( h->param.i_avcintra_class || h->param.i_ex_class) )
         h->param.analyse.i_chroma_qp_offset -= h->param.analyse.f_psy_rd < 0.25 ? 1 : 2;
     /* Psy trellis has a similar effect. */
-    if( b_open && h->mb.i_psy_trellis && !h->param.i_avcintra_class )
+    if( b_open && h->mb.i_psy_trellis && !( h->param.i_avcintra_class || h->param.i_ex_class) )
         h->param.analyse.i_chroma_qp_offset -= h->param.analyse.f_psy_trellis < 0.25 ? 1 : 2;
     h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_chroma_qp_offset, -12, 12);
     /* MB-tree requires AQ to be on, even if the strength is zero. */
@@ -1448,7 +2333,7 @@ x264_t *x264_encoder_open( x264_param_t *param )
     h->i_frame = -1;
     h->i_frame_num = 0;
 
-    if( h->param.i_avcintra_class )
+    if( h->param.i_avcintra_class || h->param.i_ex_class )
         h->i_idr_pic_id = 5;
     else
         h->i_idr_pic_id = 0;
@@ -1960,10 +2845,10 @@ static int x264_encoder_encapsulate_nals( x264_t *h, int start )
     {
         int old_payload_len = h->out.nal[i].i_payload;
         h->out.nal[i].b_long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS ||
-                                         h->param.i_avcintra_class;
+                                           h->param.i_avcintra_class || h->param.i_ex_class;
         x264_nal_encode( h, nal_buffer, &h->out.nal[i] );
         nal_buffer += h->out.nal[i].i_payload;
-        if( h->param.i_avcintra_class )
+        if( h->param.i_avcintra_class || h->param.i_ex_class )
         {
             h->out.nal[i].i_padding -= h->out.nal[i].i_payload - (old_payload_len + NALU_OVERHEAD);
             if( h->out.nal[i].i_padding > 0 )
@@ -2504,7 +3389,7 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
         x264_slice_header_init( h, &h->sh, h->sps, h->pps, h->i_idr_pic_id, h->i_frame_num, i_global_qp );
 
         /* alternate id */
-        if( h->param.i_avcintra_class )
+        if( h->param.i_avcintra_class || h->param.i_ex_class )
         {
             switch( h->i_idr_pic_id )
             {
@@ -3555,7 +4440,7 @@ int     x264_encoder_encode( x264_t *h,
             if( x264_nal_end( h ) )
                 return -1;
             /* Pad AUD/SPS to 256 bytes like Panasonic */
-            if( h->param.i_avcintra_class )
+            if( h->param.i_avcintra_class || h->param.i_ex_class )
                 h->out.nal[h->out.i_nal-1].i_padding = 256 - bs_pos( &h->out.bs ) / 8 - 2*NALU_OVERHEAD;
             overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + NALU_OVERHEAD;
 
@@ -3564,7 +4449,7 @@ int     x264_encoder_encode( x264_t *h,
             x264_pps_write( &h->out.bs, h->sps, h->pps );
             if( x264_nal_end( h ) )
                 return -1;
-            if( h->param.i_avcintra_class )
+            if( h->param.i_avcintra_class || h->param.i_ex_class )
                 h->out.nal[h->out.i_nal-1].i_padding = 256 - h->out.nal[h->out.i_nal-1].i_payload - NALU_OVERHEAD;
             overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + NALU_OVERHEAD;
         }
@@ -3607,7 +4492,7 @@ int     x264_encoder_encode( x264_t *h,
     if( h->fenc->b_keyframe )
     {
         /* Avid's decoder strictly wants two SEIs for AVC-Intra so we can't insert the x264 SEI */
-        if( h->param.b_repeat_headers && h->fenc->i_frame == 0 && !h->param.i_avcintra_class )
+        if( h->param.b_repeat_headers && h->fenc->i_frame == 0 && !( h->param.i_avcintra_class || h->param.i_ex_class ) )
         {
             /* identify ourself */
             x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
@@ -3639,7 +4524,7 @@ int     x264_encoder_encode( x264_t *h,
     }
 
     /* generate sei pic timing */
-    if( h->sps->vui.b_pic_struct_present || h->sps->vui.b_nal_hrd_parameters_present )
+    if( (h->sps->vui.b_pic_struct_present || h->sps->vui.b_nal_hrd_parameters_present) && (h->param.i_ex_class < 1) )
     {
         x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
         x264_sei_pic_timing_write( h, &h->out.bs );
@@ -3663,7 +4548,7 @@ int     x264_encoder_encode( x264_t *h,
         h->i_cpb_delay_pir_offset_next = h->fenc->i_cpb_delay;
 
     /* Filler space: 10 or 18 SEIs' worth of space, depending on resolution */
-    if( h->param.i_avcintra_class )
+    if( h->param.i_avcintra_class || h->param.i_ex_class )
     {
         /* Write an empty filler NAL to mimic the AUD in the P2 format*/
         x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE );
@@ -3774,7 +4659,7 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
     x264_emms();
 
     /* generate buffering period sei and insert it into place */
-    if( h->i_thread_frames > 1 && h->fenc->b_keyframe && h->sps->vui.b_nal_hrd_parameters_present )
+    if( h->i_thread_frames > 1 && h->fenc->b_keyframe && h->sps->vui.b_nal_hrd_parameters_present && (h->param.i_ex_class < 1) )
     {
         x264_hrd_fullness( h );
         x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
@@ -3835,7 +4720,7 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
 
     /* Filler in AVC-Intra mode is written as zero bytes to the last slice
      * We don't know the size of the last slice until encapsulation so we add filler to the encapsulated NAL */
-    if( h->param.i_avcintra_class )
+    if( h->param.i_avcintra_class || h->param.i_ex_class )
     {
         x264_t *h0 = h->thread[0];
         int ret = x264_check_encapsulated_buffer( h, h0, h->out.i_nal, frame_size, frame_size + filler );
diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
index d49e2a2..43c486f 100644
--- a/encoder/ratecontrol.c
+++ b/encoder/ratecontrol.c
@@ -2134,7 +2134,7 @@ static int update_vbv( x264_t *h, int bits )
         rct->buffer_fill_final_min = 0;
     }
 
-    if( h->param.i_avcintra_class )
+    if( h->param.i_avcintra_class || h->param.i_ex_class )
         buffer_diff = buffer_size;
     else
         buffer_diff = (uint64_t)bitrate * h->sps->vui.i_num_units_in_tick * h->fenc->i_cpb_duration;
@@ -2147,7 +2147,7 @@ static int update_vbv( x264_t *h, int bits )
         {
             int64_t scale = (int64_t)h->sps->vui.i_time_scale * 8;
             filler = (rct->buffer_fill_final - buffer_size + scale - 1) / scale;
-            bits = h->param.i_avcintra_class ? filler * 8 : X264_MAX( (FILLER_OVERHEAD - h->param.b_annexb), filler ) * 8;
+            bits = (h->param.i_avcintra_class || h->param.i_ex_class) ? filler * 8 : X264_MAX( (FILLER_OVERHEAD - h->param.b_annexb), filler ) * 8;
             buffer_diff = (uint64_t)bits * h->sps->vui.i_time_scale;
             rct->buffer_fill_final -= buffer_diff;
             rct->buffer_fill_final_min -= buffer_diff;
diff --git a/encoder/set.c b/encoder/set.c
index 9e65e62..c57baa5 100644
--- a/encoder/set.c
+++ b/encoder/set.c
@@ -166,7 +166,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
     while( (1 << sps->i_log2_max_frame_num) <= max_frame_num )
         sps->i_log2_max_frame_num++;
 
-    sps->i_poc_type = param->i_bframe || param->b_interlaced || param->i_avcintra_class ? 0 : 2;
+    sps->i_poc_type = param->i_bframe || param->b_interlaced || param->i_avcintra_class || param->i_ex_class ? 0 : 2;
     if( sps->i_poc_type == 0 )
     {
         int max_delta_poc = (param->i_bframe + 2) * (!!param->i_bframe_pyramid + 1) * 2;
@@ -241,12 +241,20 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
     if( sps->vui.b_timing_info_present )
     {
         sps->vui.i_num_units_in_tick = param->i_timebase_num;
-        sps->vui.i_time_scale = param->i_timebase_den * 2;
+        if( param->b_interlaced == 1 && param->i_ex_class > 0 )
+        {
+            sps->vui.i_time_scale = param->i_timebase_den;
+        }
+        else
+            sps->vui.i_time_scale = param->i_timebase_den * 2;
         sps->vui.b_fixed_frame_rate = !param->b_vfr_input;
     }
 
     sps->vui.b_vcl_hrd_parameters_present = 0; // we don't support VCL HRD
-    sps->vui.b_nal_hrd_parameters_present = !!param->i_nal_hrd;
+    if( param->i_ex_class <= 0 )
+    {
+        sps->vui.b_nal_hrd_parameters_present = !!param->i_nal_hrd;
+    }
     sps->vui.b_pic_struct_present = param->b_pic_struct;
 
     // NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable
@@ -423,7 +431,7 @@ void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *
     pps->i_sps_id = sps->i_id;
     pps->b_cabac = param->b_cabac;
 
-    pps->b_pic_order = !param->i_avcintra_class && param->b_interlaced;
+    pps->b_pic_order = !(param->i_avcintra_class || param->i_ex_class) && param->b_interlaced;
     pps->i_num_slice_groups = 1;
 
     pps->i_num_ref_idx_l0_default_active = param->i_frame_reference;
diff --git a/x264.c b/x264.c
index 4dd2a26..404d33c 100644
--- a/x264.c
+++ b/x264.c
@@ -895,6 +895,15 @@ static void help( x264_param_t *defaults, int longhelp )
     H1( "      --bluray-compat         Enable compatibility hacks for Blu-ray support\n" );
     H1( "      --avcintra-class <integer> Use compatibility hacks for AVC-Intra class\n"
         "                                  - 50, 100, 200\n" );
+    H1( "      --constraint <string>   Specify output constraint of AVC-Ultra or XAVC [\"class type\"]\n"
+#if BIT_DEPTH == 10
+        "                                  intra-50, intra-100, intra-200, intra-300, intra-480 \n"
+        "                                  xavc-class-x25, xavc-class-x35, xavc-class-x50 \n"
+#elif BIT_DEPTH == 12
+        "                                  intra-444-220, intra-480, intra-444-600,\n"
+#endif
+                                                                                 );
+    H1( "                              Note: Requires set FPS and resolution.\n" );
     H1( "      --stitchable            Don't optimize headers based on video content\n"
         "                              Ensures ability to recombine a segmented encode\n" );
     H1( "\n" );
@@ -952,6 +961,7 @@ typedef enum
     OPT_NOPROGRESS,
     OPT_LONGHELP,
     OPT_PROFILE,
+    OPT_CONSTRAINT,
     OPT_PRESET,
     OPT_TUNE,
     OPT_SLOWFIRSTPASS,
@@ -997,6 +1007,7 @@ static struct option long_options[] =
     { "open-gop",          no_argument, NULL, 0 },
     { "bluray-compat",     no_argument, NULL, 0 },
     { "avcintra-class", required_argument, NULL, 0 },
+    { "constraint",  required_argument, NULL, OPT_CONSTRAINT },
     { "min-keyint",  required_argument, NULL, 'i' },
     { "keyint",      required_argument, NULL, 'I' },
     { "intra-refresh",     no_argument, NULL, 0 },
@@ -1353,6 +1364,7 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
     char *tcfile_name = NULL;
     x264_param_t defaults;
     char *profile = NULL;
+    char *constraint = NULL;
     char *vid_filters = NULL;
     int b_thread_input = 0;
     int b_turbo = 1;
@@ -1474,6 +1486,10 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
             case OPT_PROFILE:
                 profile = optarg;
                 break;
+            case OPT_CONSTRAINT:
+                constraint = optarg;
+                param->i_ex_class = 1;
+                break;
             case OPT_SLOWFIRSTPASS:
                 b_turbo = 0;
                 break;
@@ -1571,7 +1587,26 @@ generic_option:
         x264_param_apply_fastfirstpass( param );
 
     /* Apply profile restrictions. */
-    if( x264_param_apply_profile( param, profile ) < 0 )
+    char profiles[32];
+    memset( profiles, 0, 32 );
+    int profile_len = 0;
+    if( param->i_ex_class )
+    {
+        if( input_opt.colorspace == NULL )
+            param->i_ex_class = 420;
+        else
+        {
+            param->i_ex_class = !strcasecmp( "i420", input_opt.colorspace ) ? 420 :
+                !strcasecmp( "i422", input_opt.colorspace ) ? 422 : !strcasecmp( "i444", input_opt.colorspace ) ? 444 : 0;
+            FAIL_IF_ERROR( !param->i_ex_class, "input colorspace is not supported for avcultra or xavc.\n" )
+        }
+        memcpy( profiles, constraint, strlen( constraint ) );
+        profiles[strlen( constraint )] = '\0';
+        profile_len = strlen( constraint ) + 1;
+    }
+    profile && memcpy( profiles + profile_len, profile, strlen( profile ) );
+
+    if( x264_param_apply_profile( param, profiles ) < 0 )
         return -1;
 
     /* Get the file name */
diff --git a/x264.h b/x264.h
index 9b6d8f4..2597ce9 100644
--- a/x264.h
+++ b/x264.h
@@ -333,6 +333,7 @@ typedef struct x264_param_t
     int         b_open_gop;
     int         b_bluray_compat;
     int         i_avcintra_class;
+    int         i_ex_class; // used for avcultra class and xavc class
 
     int         b_deblocking_filter;
     int         i_deblocking_filter_alphac0;    /* [-6, 6] -6 light filter, 6 strong */
-- 
1.9.4.msysgit.2




Regards,
 
             Xuefeng Jiang
 
xuefeng at multicorewareinc.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x264-devel/attachments/20150929/b8db5ef5/attachment-0001.html>


More information about the x264-devel mailing list