]> git.sesse.net Git - x264/blobdiff - encoder/encoder.c
allow fractional CRF values with AQ.
[x264] / encoder / encoder.c
index fcedb15a92f1d43c06039e7d47831696d1395d6e..dd74bdc4ccba3a3ed2a1053a2ab8a05f184ac95f 100644 (file)
 #endif
 
 //#define DEBUG_MB_TYPE
-//#define DEBUG_DUMP_FRAME
-//#define DEBUG_BENCHMARK
-
-#ifdef DEBUG_BENCHMARK
-static int64_t i_mtime_encode_frame = 0;
-static int64_t i_mtime_analyse = 0;
-static int64_t i_mtime_encode = 0;
-static int64_t i_mtime_write = 0;
-static int64_t i_mtime_filter = 0;
-#define TIMER_START( d ) \
-    { \
-        int64_t d##start = x264_mdate();
-
-#define TIMER_STOP( d ) \
-        d += x264_mdate() - d##start;\
-    }
-#else
-#define TIMER_START( d )
-#define TIMER_STOP( d )
-#endif
 
 #define NALU_OVERHEAD 5 // startcode + NAL type costs 5 bytes per frame
 
@@ -77,27 +57,19 @@ static float x264_psnr( int64_t i_sqe, int64_t i_size )
     return (float)(-10.0 * log( f_mse ) / log( 10.0 ));
 }
 
-#ifdef DEBUG_DUMP_FRAME
-static void x264_frame_dump( x264_t *h, x264_frame_t *fr, char *name )
+static void x264_frame_dump( x264_t *h )
 {
-    FILE *f = fopen( name, "r+b" );
+    FILE *f = fopen( h->param.psz_dump_yuv, "r+b" );
     int i, y;
     if( !f )
         return;
-
     /* Write the frame in display order */
-    fseek( f, fr->i_frame * h->param.i_height * h->param.i_width * 3 / 2, SEEK_SET );
-
-    for( i = 0; i < fr->i_plane; i++ )
-    {
-        for( y = 0; y < h->param.i_height / ( i == 0 ? 1 : 2 ); y++ )
-        {
-            fwrite( &fr->plane[i][y*fr->i_stride[i]], 1, h->param.i_width / ( i == 0 ? 1 : 2 ), f );
-        }
-    }
+    fseek( f, h->fdec->i_frame * h->param.i_height * h->param.i_width * 3/2, SEEK_SET );
+    for( i = 0; i < h->fdec->i_plane; i++ )
+        for( y = 0; y < h->param.i_height >> !!i; y++ )
+            fwrite( &h->fdec->plane[i][y*h->fdec->i_stride[i]], 1, h->param.i_width >> !!i, f );
     fclose( f );
 }
-#endif
 
 
 /* Fill "default" values */
@@ -363,7 +335,7 @@ static int x264_validate_parameters( x264_t *h )
 
     if( h->param.b_interlaced )
     {
-        if( h->param.analyse.i_me_method == X264_ME_ESA )
+        if( h->param.analyse.i_me_method >= X264_ME_ESA )
         {
             x264_log( h, X264_LOG_WARNING, "interlace + me=esa is not implemented\n" );
             h->param.analyse.i_me_method = X264_ME_UMH;
@@ -401,6 +373,7 @@ static int x264_validate_parameters( x264_t *h )
         h->param.analyse.b_fast_pskip = 0;
         h->param.analyse.i_noise_reduction = 0;
         h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 6 );
+        h->param.rc.i_aq_mode = 0;
     }
     if( h->param.rc.i_rc_method == X264_RC_CQP )
     {
@@ -449,12 +422,15 @@ static int x264_validate_parameters( x264_t *h )
         h->param.i_cqm_preset = X264_CQM_FLAT;
 
     if( h->param.analyse.i_me_method < X264_ME_DIA ||
-        h->param.analyse.i_me_method > X264_ME_ESA )
+        h->param.analyse.i_me_method > X264_ME_TESA )
         h->param.analyse.i_me_method = X264_ME_HEX;
     if( h->param.analyse.i_me_range < 4 )
         h->param.analyse.i_me_range = 4;
     if( h->param.analyse.i_me_range > 16 && h->param.analyse.i_me_method <= X264_ME_HEX )
         h->param.analyse.i_me_range = 16;
+    if( h->param.analyse.i_me_method == X264_ME_TESA &&
+        (h->mb.b_lossless || h->param.analyse.i_subpel_refine <= 1) )
+        h->param.analyse.i_me_method = X264_ME_ESA;
     h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 7 );
     h->param.analyse.b_bframe_rdo = h->param.analyse.b_bframe_rdo && h->param.analyse.i_subpel_refine >= 6;
     h->param.analyse.b_mixed_references = h->param.analyse.b_mixed_references && h->param.i_frame_reference > 1;
@@ -472,6 +448,12 @@ static int x264_validate_parameters( x264_t *h )
     if( !h->param.b_cabac )
         h->param.analyse.i_trellis = 0;
     h->param.analyse.i_trellis = x264_clip3( h->param.analyse.i_trellis, 0, 2 );
+    h->param.rc.i_aq_mode = x264_clip3( h->param.rc.i_aq_mode, 0, 2 );
+    if( h->param.rc.f_aq_strength <= 0 )
+        h->param.rc.i_aq_mode = 0;
+    /* VAQ effectively replaces qcomp, so qcomp is raised towards 1 to compensate. */
+    if( h->param.rc.i_aq_mode == X264_AQ_GLOBAL )
+        h->param.rc.f_qcompress = x264_clip3f(h->param.rc.f_qcompress + h->param.rc.f_aq_strength / 0.7, 0, 1);
     h->param.analyse.i_noise_reduction = x264_clip3( h->param.analyse.i_noise_reduction, 0, 1<<16 );
 
     {
@@ -546,9 +528,12 @@ static int x264_validate_parameters( x264_t *h )
 
 static void mbcmp_init( x264_t *h )
 {
-    memcpy( h->pixf.mbcmp,
-            ( h->mb.b_lossless || h->param.analyse.i_subpel_refine <= 1 ) ? h->pixf.sad : h->pixf.satd,
-            sizeof(h->pixf.mbcmp) );
+    int satd = !h->mb.b_lossless && h->param.analyse.i_subpel_refine > 1;
+    memcpy( h->pixf.mbcmp, satd ? h->pixf.satd : h->pixf.sad, sizeof(h->pixf.mbcmp) );
+    satd &= h->param.analyse.i_me_method == X264_ME_TESA;
+    memcpy( h->pixf.fpelcmp, satd ? h->pixf.satd : h->pixf.sad, sizeof(h->pixf.fpelcmp) );
+    memcpy( h->pixf.fpelcmp_x3, satd ? h->pixf.satd_x3 : h->pixf.sad_x3, sizeof(h->pixf.fpelcmp_x3) );
+    memcpy( h->pixf.fpelcmp_x4, satd ? h->pixf.satd_x4 : h->pixf.sad_x4, sizeof(h->pixf.fpelcmp_x4) );
 }
 
 /****************************************************************************
@@ -557,6 +542,7 @@ static void mbcmp_init( x264_t *h )
 x264_t *x264_encoder_open   ( x264_param_t *param )
 {
     x264_t *h = x264_malloc( sizeof( x264_t ) );
+    char buf[1000], *p;
     int i;
 
     memset( h, 0, sizeof( x264_t ) );
@@ -645,6 +631,7 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
           || h->param.rc.i_rc_method == X264_RC_CRF
           || h->param.b_bframe_adaptive
           || h->param.b_pre_scenecut );
+    h->frames.b_have_lowres |= (h->param.rc.b_stat_read && h->param.rc.i_vbv_buffer_size > 0);
 
     h->frames.i_last_idr = - h->param.i_keyint_max;
     h->frames.i_input    = 0;
@@ -665,22 +652,20 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
     x264_dct_init( h->param.cpu, &h->dctf );
     x264_zigzag_init( h->param.cpu, &h->zigzagf, h->param.b_interlaced );
     x264_mc_init( h->param.cpu, &h->mc );
-    x264_csp_init( h->param.cpu, h->param.i_csp, &h->csp );
     x264_quant_init( h, h->param.cpu, &h->quantf );
     x264_deblock_init( h->param.cpu, &h->loopf );
     x264_dct_init_weights();
 
     mbcmp_init( h );
 
-    x264_log( h, X264_LOG_INFO, "using cpu capabilities: %s%s%s%s%s%s%s%s\n",
-             param->cpu&X264_CPU_MMX ? "MMX " : "",
-             param->cpu&X264_CPU_MMXEXT ? "MMXEXT " : "",
-             param->cpu&X264_CPU_SSE ? "SSE " : "",
-             param->cpu&X264_CPU_SSE2 ? "SSE2 " : "",
-             param->cpu&X264_CPU_SSSE3 ? "SSSE3 " : "",
-             param->cpu&X264_CPU_3DNOW ? "3DNow! " : "",
-             param->cpu&X264_CPU_ALTIVEC ? "Altivec " : "",
-             param->cpu ? "" : "none!" );
+    p = buf + sprintf( buf, "using cpu capabilities:" );
+    for( i=0; x264_cpu_names[i].flags; i++ )
+        if( (param->cpu & x264_cpu_names[i].flags) == x264_cpu_names[i].flags
+            && (!i || x264_cpu_names[i].flags != x264_cpu_names[i-1].flags) )
+            p += sprintf( p, " %s", x264_cpu_names[i].name );
+    if( !param->cpu )
+        p += sprintf( p, " none!" );
+    x264_log( h, X264_LOG_INFO, "%s\n", buf );
 
     h->out.i_nal = 0;
     h->out.i_bitstream = X264_MAX( 1000000, h->param.i_width * h->param.i_height * 4
@@ -705,10 +690,10 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
     if( x264_ratecontrol_new( h ) < 0 )
         return NULL;
 
-#ifdef DEBUG_DUMP_FRAME
+    if( h->param.psz_dump_yuv )
     {
         /* create or truncate the reconstructed video file */
-        FILE *f = fopen( "fdec.yuv", "w" );
+        FILE *f = fopen( h->param.psz_dump_yuv, "w" );
         if( f )
             fclose( f );
         else
@@ -718,7 +703,6 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
             return NULL;
         }
     }
-#endif
 
     return h;
 }
@@ -881,7 +865,7 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
     h->i_ref1 = X264_MIN( h->i_ref1, h->frames.i_max_ref1 );
     h->i_ref0 = X264_MIN( h->i_ref0, h->frames.i_max_ref0 );
     h->i_ref0 = X264_MIN( h->i_ref0, h->param.i_frame_reference ); // if reconfig() has lowered the limit
-    h->i_ref0 = X264_MIN( h->i_ref0, 16 - h->i_ref1 );
+    assert( h->i_ref0 + h->i_ref1 <= 16 );
     h->mb.pic.i_fref[0] = h->i_ref0;
     h->mb.pic.i_fref[1] = h->i_ref1;
 }
@@ -893,9 +877,7 @@ static void x264_fdec_filter_row( x264_t *h, int mb_y )
     int b_deblock = !h->sh.i_disable_deblocking_filter_idc;
     int b_end = mb_y == h->sps->i_mb_height;
     int min_y = mb_y - (1 << h->sh.b_mbaff);
-#ifndef DEBUG_DUMP_FRAME
-    b_deblock &= b_hpel;
-#endif
+    b_deblock &= b_hpel || h->param.psz_dump_yuv;
     if( mb_y & h->sh.b_mbaff )
         return;
     if( min_y < 0 )
@@ -924,7 +906,7 @@ static void x264_fdec_filter_row( x264_t *h, int mb_y )
     if( b_hpel )
     {
         x264_frame_expand_border( h, h->fdec, min_y, b_end );
-        x264_frame_filter( h->param.cpu, h->fdec, h->sh.b_mbaff, min_y, b_end );
+        x264_frame_filter( h, h->fdec, min_y, b_end );
         x264_frame_expand_border_filtered( h, h->fdec, min_y, b_end );
     }
 
@@ -1019,7 +1001,7 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
 static void x264_slice_write( x264_t *h )
 {
     int i_skip;
-    int mb_xy;
+    int mb_xy, i_mb_x, i_mb_y;
     int i;
 
     /* init stats */
@@ -1042,10 +1024,12 @@ static void x264_slice_write( x264_t *h )
     h->mb.i_last_qp = h->sh.i_qp;
     h->mb.i_last_dqp = 0;
 
-    for( mb_xy = h->sh.i_first_mb, i_skip = 0; mb_xy < h->sh.i_last_mb; )
+    i_mb_y = h->sh.i_first_mb / h->sps->i_mb_width;
+    i_mb_x = h->sh.i_first_mb % h->sps->i_mb_width;
+    i_skip = 0;
+
+    while( (mb_xy = i_mb_x + i_mb_y * h->sps->i_mb_width) < h->sh.i_last_mb )
     {
-        const int i_mb_y = mb_xy / h->sps->i_mb_width;
-        const int i_mb_x = mb_xy % h->sps->i_mb_width;
         int mb_spos = bs_pos(&h->out.bs) + x264_cabac_pos(&h->cabac);
 
         if( i_mb_x == 0 )
@@ -1058,20 +1042,15 @@ static void x264_slice_write( x264_t *h )
          * Slice I: choose I_4x4 or I_16x16 mode
          * Slice P: choose between using P mode or intra (4x4 or 16x16)
          * */
-        TIMER_START( i_mtime_analyse );
         x264_macroblock_analyse( h );
-        TIMER_STOP( i_mtime_analyse );
 
         /* encode this macroblock -> be careful it can change the mb type to P_SKIP if needed */
-        TIMER_START( i_mtime_encode );
         x264_macroblock_encode( h );
-        TIMER_STOP( i_mtime_encode );
 
-        TIMER_START( i_mtime_write );
         if( h->param.b_cabac )
         {
             if( mb_xy > h->sh.i_first_mb && !(h->sh.b_mbaff && (i_mb_y&1)) )
-                x264_cabac_encode_terminal( &h->cabac, 0 );
+                x264_cabac_encode_terminal( &h->cabac );
 
             if( IS_SKIP( h->mb.i_type ) )
                 x264_cabac_mb_skip( h, 1 );
@@ -1096,7 +1075,6 @@ static void x264_slice_write( x264_t *h )
                 x264_macroblock_write_cavlc( h, &h->out.bs );
             }
         }
-        TIMER_STOP( i_mtime_write );
 
 #if VISUALIZE
         if( h->param.b_visualize )
@@ -1131,45 +1109,39 @@ static void x264_slice_write( x264_t *h )
             h->stat.frame.i_mb_count_8x8dct[1] += h->mb.b_transform_8x8;
         }
 
-        if( h->mb.b_variable_qp )
-            x264_ratecontrol_mb(h, bs_pos(&h->out.bs) + x264_cabac_pos(&h->cabac) - mb_spos);
+        x264_ratecontrol_mb( h, bs_pos(&h->out.bs) + x264_cabac_pos(&h->cabac) - mb_spos );
 
         if( h->sh.b_mbaff )
         {
-            if( (i_mb_y&1) && i_mb_x == h->sps->i_mb_width - 1 )
-                mb_xy++;
-            else if( i_mb_y&1 )
-                mb_xy += 1 - h->sps->i_mb_width;
-            else
-                mb_xy += h->sps->i_mb_width;
+            i_mb_x += i_mb_y & 1;
+            i_mb_y ^= i_mb_x < h->sps->i_mb_width;
         }
         else
-            mb_xy++;
-    }
-
-    if( h->param.b_cabac )
-    {
-        /* end of slice */
-        x264_cabac_encode_terminal( &h->cabac, 1 );
-    }
-    else if( i_skip > 0 )
-    {
-        bs_write_ue( &h->out.bs, i_skip );  /* last skip run */
+            i_mb_x++;
+        if(i_mb_x == h->sps->i_mb_width)
+        {
+            i_mb_y++;
+            i_mb_x = 0;
+        }
     }
 
     if( h->param.b_cabac )
     {
-        x264_cabac_encode_flush( &h->cabac );
+        x264_cabac_encode_flush( h, &h->cabac );
         h->out.bs.p = h->cabac.p;
     }
     else
     {
+        if( i_skip > 0 )
+            bs_write_ue( &h->out.bs, i_skip );  /* last skip run */
         /* rbsp_slice_trailing_bits */
         bs_rbsp_trailing( &h->out.bs );
     }
 
     x264_nal_end( h );
 
+    x264_fdec_filter_row( h, h->sps->i_mb_height );
+
     /* Compute misc bits */
     h->stat.frame.i_misc_bits = bs_pos( &h->out.bs )
                               + NALU_OVERHEAD * 8
@@ -1216,7 +1188,6 @@ static int x264_slices_write( x264_t *h )
 
     x264_stack_align( x264_slice_write, h );
     i_frame_size = h->out.nal[h->out.i_nal-1].i_payload;
-    x264_fdec_filter_row( h, h->sps->i_mb_height );
 
 #if VISUALIZE
     if( h->param.b_visualize )
@@ -1282,13 +1253,13 @@ int     x264_encoder_encode( x264_t *h,
     *pp_nal = NULL;
 
     /* ------------------- Setup new frame from picture -------------------- */
-    TIMER_START( i_mtime_encode_frame );
     if( pic_in != NULL )
     {
         /* 1: Copy the picture to a frame and move it to a buffer */
         x264_frame_t *fenc = x264_frame_pop_unused( h );
 
-        x264_frame_copy_picture( h, fenc, pic_in );
+        if( x264_frame_copy_picture( h, fenc, pic_in ) < 0 )
+            return -1;
 
         if( h->param.i_width != 16 * h->sps->i_mb_width ||
             h->param.i_height != 16 * h->sps->i_mb_height )
@@ -1299,7 +1270,7 @@ int     x264_encoder_encode( x264_t *h,
         x264_frame_push( h->frames.next, fenc );
 
         if( h->frames.b_have_lowres )
-            x264_frame_init_lowres( h->param.cpu, fenc );
+            x264_frame_init_lowres( h, fenc );
 
         if( h->frames.i_input <= h->frames.i_delay + 1 - h->param.i_threads )
         {
@@ -1337,7 +1308,6 @@ int     x264_encoder_encode( x264_t *h,
         while( bframes-- )
             x264_frame_push( h->frames.current, x264_frame_shift( h->frames.next ) );
     }
-    TIMER_STOP( i_mtime_encode_frame );
 
     /* ------------------- Get frame to be encoded ------------------------- */
     /* 4: get picture to encode */
@@ -1359,7 +1329,6 @@ do_encode:
 
     /* ------------------- Setup frame context ----------------------------- */
     /* 5: Init data dependent of frame type */
-    TIMER_START( i_mtime_encode_frame );
     if( h->fenc->i_type == X264_TYPE_IDR )
     {
         /* reset ref pictures */
@@ -1481,7 +1450,7 @@ do_encode:
         x264_slices_write( h );
 
     /* restore CPU state (before using float again) */
-    x264_cpu_restore( h->param.cpu );
+    x264_emms();
 
     if( h->sh.i_type == SLICE_TYPE_P && !h->param.rc.b_stat_read 
         && h->param.i_scenecut_threshold >= 0
@@ -1628,15 +1597,13 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
     /* ---------------------- Update encoder state ------------------------- */
 
     /* update rc */
-    x264_cpu_restore( h->param.cpu );
+    x264_emms();
     x264_ratecontrol_end( h, h->out.i_frame_size * 8 );
 
     /* restore CPU state (before using float again) */
-    x264_cpu_restore( h->param.cpu );
-
-    x264_noise_reduction_update( h );
+    x264_emms();
 
-    TIMER_STOP( i_mtime_encode_frame );
+    x264_noise_reduction_update( thread_current );
 
     /* ---------------------- Compute/Print statistics --------------------- */
     x264_thread_sync_stat( h, h->thread[0] );
@@ -1644,7 +1611,7 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
     /* Slice stat */
     h->stat.i_slice_count[h->sh.i_type]++;
     h->stat.i_slice_size[h->sh.i_type] += h->out.i_frame_size + NALU_OVERHEAD;
-    h->stat.i_slice_qp[h->sh.i_type] += h->fdec->i_qpplus1 - 1;
+    h->stat.f_slice_qp[h->sh.i_type] += h->fdec->f_qp_avg_aq;
 
     for( i = 0; i < X264_MBTYPE_MAX; i++ )
         h->stat.i_mb_count[h->sh.i_type][i] += h->stat.frame.i_mb_count[i];
@@ -1685,7 +1652,7 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
                          h->fenc->plane[i], h->fenc->i_stride[i],
                          h->param.i_width >> !!i, h->param.i_height >> !!i );
         }
-        x264_cpu_restore( h->param.cpu );
+        x264_emms();
 
         h->stat.i_sqe_global[h->sh.i_type] += sqe[0] + sqe[1] + sqe[2];
         h->stat.f_psnr_average[h->sh.i_type] += x264_psnr( sqe[0] + sqe[1] + sqe[2], 3 * h->param.i_width * h->param.i_height / 2 );
@@ -1713,9 +1680,9 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
     psz_message[79] = '\0';
     
     x264_log( h, X264_LOG_DEBUG,
-                  "frame=%4d QP=%i NAL=%d Slice:%c Poc:%-3d I:%-4d P:%-4d SKIP:%-4d size=%d bytes%s\n",
+                  "frame=%4d QP=%.2f NAL=%d Slice:%c Poc:%-3d I:%-4d P:%-4d SKIP:%-4d size=%d bytes%s\n",
               h->i_frame,
-              h->fdec->i_qpplus1 - 1,
+              h->fdec->f_qp_avg_aq,
               h->i_nal_ref_idc,
               h->sh.i_type == SLICE_TYPE_I ? 'I' : (h->sh.i_type == SLICE_TYPE_P ? 'P' : 'B' ),
               h->fdec->i_poc,
@@ -1748,10 +1715,8 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
 }
 #endif
 
-#ifdef DEBUG_DUMP_FRAME
-    /* Dump reconstructed frame */
-    x264_frame_dump( h, h->fdec, "fdec.yuv" );
-#endif
+    if( h->param.psz_dump_yuv )
+        x264_frame_dump( h );
 }
 
 /****************************************************************************
@@ -1759,9 +1724,6 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
  ****************************************************************************/
 void    x264_encoder_close  ( x264_t *h )
 {
-#ifdef DEBUG_BENCHMARK
-    int64_t i_mtime_total = i_mtime_analyse + i_mtime_encode + i_mtime_write + i_mtime_filter + 1;
-#endif
     int64_t i_yuv_size = 3 * h->param.i_width * h->param.i_height / 2;
     int i;
 
@@ -1772,15 +1734,6 @@ void    x264_encoder_close  ( x264_t *h )
             x264_pthread_join( h->thread[i]->thread_handle, NULL );
     }
 
-#ifdef DEBUG_BENCHMARK
-    x264_log( h, X264_LOG_INFO,
-              "analyse=%d(%lldms) encode=%d(%lldms) write=%d(%lldms) filter=%d(%lldms)\n",
-              (int)(100*i_mtime_analyse/i_mtime_total), i_mtime_analyse/1000,
-              (int)(100*i_mtime_encode/i_mtime_total), i_mtime_encode/1000,
-              (int)(100*i_mtime_write/i_mtime_total), i_mtime_write/1000,
-              (int)(100*i_mtime_filter/i_mtime_total), i_mtime_filter/1000 );
-#endif
-
     /* Slices used and PSNR */
     for( i=0; i<5; i++ )
     {
@@ -1797,7 +1750,7 @@ void    x264_encoder_close  ( x264_t *h )
                           "slice %s:%-5d Avg QP:%5.2f  size:%6.0f  PSNR Mean Y:%5.2f U:%5.2f V:%5.2f Avg:%5.2f Global:%5.2f\n",
                           slice_name[i_slice],
                           i_count,
-                          (double)h->stat.i_slice_qp[i_slice] / i_count,
+                          h->stat.f_slice_qp[i_slice] / i_count,
                           (double)h->stat.i_slice_size[i_slice] / i_count,
                           h->stat.f_psnr_mean_y[i_slice] / i_count, h->stat.f_psnr_mean_u[i_slice] / i_count, h->stat.f_psnr_mean_v[i_slice] / i_count,
                           h->stat.f_psnr_average[i_slice] / i_count,
@@ -1809,7 +1762,7 @@ void    x264_encoder_close  ( x264_t *h )
                           "slice %s:%-5d Avg QP:%5.2f  size:%6.0f\n",
                           slice_name[i_slice],
                           i_count,
-                          (double)h->stat.i_slice_qp[i_slice] / i_count,
+                          h->stat.f_slice_qp[i_slice] / i_count,
                           (double)h->stat.i_slice_size[i_slice] / i_count );
             }
         }