]> git.sesse.net Git - x264/commitdiff
Add support for AVC-Intra Class 200
authorKieran Kunhya <kieran@kunhya.com>
Fri, 10 Jan 2014 23:27:33 +0000 (23:27 +0000)
committerFiona Glaser <fiona@x264.com>
Tue, 21 Jan 2014 21:40:14 +0000 (13:40 -0800)
common/common.c
common/common.h
encoder/analyse.c
encoder/encoder.c
encoder/ratecontrol.c
encoder/set.c
x264.c
x264.h

index 76e80b948606149f04b8a422ff962f6eb9825f87..a9e1c7325246cb594d71a4f5d47ee4fde0649f34 100644 (file)
@@ -671,8 +671,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
     }
     OPT("bluray-compat")
         p->b_bluray_compat = atobool(value);
-    OPT("avcintra-compat")
-        p->b_avcintra_compat = atobool(value);
+    OPT("avcintra-class")
+        p->i_avcintra_class = atoi(value);
     OPT("sar")
     {
         b_error = ( 2 != sscanf( value, "%d:%d", &p->vui.i_sar_width, &p->vui.i_sar_height ) &&
index fa8fab360b367bc7c8db87a064bcdd33a53816dd..ab14a6326e59b0de26dcbc563a00a7e25ca38e19 100644 (file)
@@ -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.b_avcintra_compat && (h->out.i_nal-1)))
+#define SEI_OVERHEAD (NALU_OVERHEAD - (h->param.b_annexb && !h->param.i_avcintra_class && (h->out.i_nal-1)))
 
 /****************************************************************************
  * Includes
index 0e8a280f11506fe29f2da6d0eb54daf9051c9396..9131d3d709d928a514afadc28f2f6f22f9be4483 100644 (file)
@@ -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.b_avcintra_compat && !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->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.b_avcintra_compat )
+    if( !h->param.i_avcintra_class )
     {
         const int8_t *predict_mode = predict_16x16_mode_available( h->mb.i_neighbour_intra );
 
index d7302963467a19e1eb28a5aaca03109487e80d5f..4ef02ed296d668daa9e927f2600a5eedf2dfd7fa 100644 (file)
@@ -609,7 +609,7 @@ static int x264_validate_parameters( x264_t *h, int b_open )
     if( PARAM_INTERLACED )
         h->param.b_pic_struct = 1;
 
-    if( h->param.b_avcintra_compat )
+    if( h->param.i_avcintra_class )
     {
         if( BIT_DEPTH != 10 )
         {
@@ -618,7 +618,16 @@ static int x264_validate_parameters( x264_t *h, int b_open )
             return -1;
         }
 
-        /* [50/100][res][fps] */
+        int type = h->param.i_avcintra_class == 200 ? 2 :
+                   h->param.i_avcintra_class == 100 ? 1 :
+                   h->param.i_avcintra_class == 50 ? 0 : -1;
+        if( type < 0 )
+        {
+            x264_log( h, X264_LOG_ERROR, "Invalid AVC-Intra class\n" );
+            return -1;
+        }
+
+        /* [50/100/200][res][fps] */
         static const struct
         {
             uint16_t fps_num;
@@ -627,7 +636,7 @@ static int x264_validate_parameters( x264_t *h, int b_open )
             uint16_t frame_size;
             const uint8_t *cqm_4ic;
             const uint8_t *cqm_8iy;
-        } avcintra_lut[2][2][7] =
+        } avcintra_lut[3][2][7] =
         {
             {{{ 60000, 1001, 0,  912, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy },
               {    50,    1, 0, 1100, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy },
@@ -652,31 +661,39 @@ static int x264_validate_parameters( x264_t *h, int b_open )
               { 30000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
               {    50,    1, 0, 4444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
               {    25,    1, 0, 4444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
-              { 24000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}}
+              { 24000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}},
+            {{{ 60000, 1001, 0, 3724, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy },
+              {    50,    1, 0, 4472, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy }},
+             {{ 30000, 1001, 1, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy },
+              {    25,    1, 1, 8940, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy },
+              { 60000, 1001, 0, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
+              { 30000, 1001, 0, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
+              {    50,    1, 0, 8940, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
+              {    25,    1, 0, 8940, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
+              { 24000, 1001, 0, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}}
         };
 
         int res = -1;
-        int type = i_csp == X264_CSP_I422;
-        if( type )
-        {
-            if(      h->param.i_width == 1920 && h->param.i_height == 1080 ) res =  1;
-            else if( h->param.i_width == 1280 && h->param.i_height ==  720 ) res =  0;
-        }
-        else if( i_csp == X264_CSP_I420 )
+        if( i_csp >= X264_CSP_I420 && i_csp < X264_CSP_I422 && !type )
         {
             if(      h->param.i_width == 1440 && h->param.i_height == 1080 ) res =  1;
             else if( h->param.i_width ==  960 && h->param.i_height ==  720 ) res =  0;
         }
+        else if( i_csp >= X264_CSP_I422 && i_csp < X264_CSP_I444 && type )
+        {
+            if(      h->param.i_width == 1920 && h->param.i_height == 1080 ) res =  1;
+            else if( h->param.i_width == 1280 && h->param.i_height ==  720 ) res =  0;
+        }
         else
         {
-            x264_log( h, X264_LOG_ERROR, "Invalid colorspace for AVC-Intra\n" );
+            x264_log( h, X264_LOG_ERROR, "Invalid colorspace for AVC-Intra %d\n", h->param.i_avcintra_class );
             return -1;
         }
 
         if( res < 0 )
         {
-            x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid for AVC-Intra %s\n",
-                      h->param.i_width, h->param.i_height, type ? "100" : "50" );
+            x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid for AVC-Intra %d\n",
+                      h->param.i_width, h->param.i_height, h->param.i_avcintra_class );
             return -1;
         }
 
@@ -765,8 +782,9 @@ static int x264_validate_parameters( x264_t *h, int b_open )
             h->param.vui.i_sar_height = 3;
         }
 
-        /* Avid cannot handle negative QPs */
-        h->param.rc.i_qp_min = X264_MAX( h->param.rc.i_qp_min, QP_BD_OFFSET );
+        /* Official encoder doesn't appear to go under 13
+         * and Avid cannot handle negative QPs */
+        h->param.rc.i_qp_min = X264_MAX( h->param.rc.i_qp_min, QP_BD_OFFSET + 1 );
     }
 
     h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, -QP_BD_OFFSET, 51 );
@@ -1070,10 +1088,10 @@ static int x264_validate_parameters( x264_t *h, int b_open )
         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.b_avcintra_compat )
+    if( b_open && h->mb.i_psy_rd && !h->param.i_avcintra_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.b_avcintra_compat )
+    if( b_open && h->mb.i_psy_trellis && !h->param.i_avcintra_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. */
@@ -1234,7 +1252,6 @@ static int x264_validate_parameters( x264_t *h, int b_open )
     BOOLIFY( b_stitchable );
     BOOLIFY( b_full_recon );
     BOOLIFY( b_opencl );
-    BOOLIFY( b_avcintra_compat );
     BOOLIFY( analyse.b_transform_8x8 );
     BOOLIFY( analyse.b_weighted_bipred );
     BOOLIFY( analyse.b_chroma_me );
@@ -1894,10 +1911,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.b_avcintra_compat;
+                                         h->param.i_avcintra_class;
         x264_nal_encode( h, nal_buffer, &h->out.nal[i] );
         nal_buffer += h->out.nal[i].i_payload;
-        if( h->param.b_avcintra_compat )
+        if( h->param.i_avcintra_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 )
@@ -3443,7 +3460,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.b_avcintra_compat )
+            if( h->param.i_avcintra_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;
 
@@ -3452,7 +3469,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.b_avcintra_compat )
+            if( h->param.i_avcintra_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;
         }
@@ -3495,7 +3512,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.b_avcintra_compat )
+        if( h->param.b_repeat_headers && h->fenc->i_frame == 0 && !h->param.i_avcintra_class )
         {
             /* identify ourself */
             x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
@@ -3551,7 +3568,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.b_avcintra_compat )
+    if( h->param.i_avcintra_class )
     {
         /* Write an empty filler NAL to mimic the AUD in the P2 format*/
         x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE );
@@ -3723,7 +3740,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.b_avcintra_compat )
+    if( h->param.i_avcintra_class )
     {
         x264_t *h0 = h->thread[0];
         int ret = x264_check_encapsulated_buffer( h, h0, h->out.i_nal, frame_size, frame_size + filler );
index 3bf62d17c06358a9e59c3916e9dbab9b9fabd0ec..e408b00f34a2c4a4f08e723d710c70423c3de8c9 100644 (file)
@@ -653,7 +653,7 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
                       h->param.rc.i_vbv_buffer_size );
         }
 
-        int kilobit_size = h->param.b_avcintra_compat ? 1024 : 1000;
+        int kilobit_size = h->param.i_avcintra_class ? 1024 : 1000;
         int vbv_buffer_size = h->param.rc.i_vbv_buffer_size * kilobit_size;
         int vbv_max_bitrate = h->param.rc.i_vbv_max_bitrate * kilobit_size;
 
@@ -759,7 +759,7 @@ int x264_ratecontrol_new( x264_t *h )
     else
         rc->qcompress = h->param.rc.f_qcompress;
 
-    rc->bitrate = h->param.rc.i_bitrate * (h->param.b_avcintra_compat ? 1024. : 1000.);
+    rc->bitrate = h->param.rc.i_bitrate * (h->param.i_avcintra_class ? 1024. : 1000.);
     rc->rate_tolerance = h->param.rc.f_rate_tolerance;
     rc->nmb = h->mb.i_mb_count;
     rc->last_non_b_pict_type = -1;
@@ -2115,7 +2115,7 @@ static int update_vbv( x264_t *h, int bits )
     }
     rct->buffer_fill_final = X264_MAX( rct->buffer_fill_final, 0 );
 
-    if( h->param.b_avcintra_compat )
+    if( h->param.i_avcintra_class )
         rct->buffer_fill_final += buffer_size;
     else
         rct->buffer_fill_final += (uint64_t)bitrate * h->sps->vui.i_num_units_in_tick * h->fenc->i_cpb_duration;
@@ -2124,7 +2124,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.b_avcintra_compat ? filler * 8 : X264_MAX( (FILLER_OVERHEAD - h->param.b_annexb), filler ) * 8;
+        bits = h->param.i_avcintra_class ? filler * 8 : X264_MAX( (FILLER_OVERHEAD - h->param.b_annexb), filler ) * 8;
         rct->buffer_fill_final -= (uint64_t)bits * h->sps->vui.i_time_scale;
     }
     else
index c3aa7c28b221eec1e1428ecfe2f9f34502196e16..e867a7d7d846f07d0ed2a5a89ceba41d67f038ed 100644 (file)
@@ -422,7 +422,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->b_avcintra_compat && param->b_interlaced;
+    pps->b_pic_order = !param->i_avcintra_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 79d141086a4ada3f04f3c69478ee3313bd2bb19b..f1c758ac2bea5ac475b82d2fad064ea12bdbd91a 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -880,7 +880,8 @@ static void help( x264_param_t *defaults, int longhelp )
     H0( "      --frames <integer>      Maximum number of frames to encode\n" );
     H0( "      --level <string>        Specify level (as defined by Annex A)\n" );
     H1( "      --bluray-compat         Enable compatibility hacks for Blu-ray support\n" );
-    H1( "      --avcintra-compat       Enable compatibility hacks for AVC-Intra support\n" );
+    H1( "      --avcintra-class <integer> Use compatibility hacks for AVC-Intra class\n"
+        "                                  - 50, 100, 200\n" );
     H1( "      --stitchable            Don't optimize headers based on video content\n"
         "                              Ensures ability to recombine a segmented encode\n" );
     H1( "\n" );
@@ -982,7 +983,7 @@ static struct option long_options[] =
     { "b-pyramid",   required_argument, NULL, 0 },
     { "open-gop",          no_argument, NULL, 0 },
     { "bluray-compat",     no_argument, NULL, 0 },
-    { "avcintra-compat",   no_argument, NULL, 0 },
+    { "avcintra-class", required_argument, NULL, 0 },
     { "min-keyint",  required_argument, NULL, 'i' },
     { "keyint",      required_argument, NULL, 'I' },
     { "intra-refresh",     no_argument, NULL, 0 },
diff --git a/x264.h b/x264.h
index 625a2d9e0bc007df8e48729ecb7eba1b2ed85b3b..6ad6308082a0a3dacbdd8e6d5b809448b71f10c2 100644 (file)
--- a/x264.h
+++ b/x264.h
@@ -41,7 +41,7 @@
 
 #include "x264_config.h"
 
-#define X264_BUILD 141
+#define X264_BUILD 142
 
 /* Application developers planning to link against a shared library version of
  * libx264 from a Microsoft Visual Studio or similar development environment
@@ -322,7 +322,7 @@ typedef struct x264_param_t
     int         i_bframe_pyramid;   /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */
     int         b_open_gop;
     int         b_bluray_compat;
-    int         b_avcintra_compat;
+    int         i_avcintra_class;
 
     int         b_deblocking_filter;
     int         i_deblocking_filter_alphac0;    /* [-6, 6] -6 light filter, 6 strong */