]> git.sesse.net Git - x264/blobdiff - encoder/encoder.c
* x264 compilation on NetBSD. Patch by Mike Matsnev.
[x264] / encoder / encoder.c
index 854aa792cd5e3670200635d48cbd987418cb7c00..4f5f6cd6eeee767aae5ab48d10f14a8fbfd16a60 100644 (file)
 #include <string.h>
 #include <math.h>
 
-#if HAVE_PTHREAD
-#ifdef SYS_BEOS
+#ifdef __WIN32__
+#include <windows.h>
+#define pthread_t               HANDLE
+#define pthread_create(t,u,f,d) *(t)=CreateThread(NULL,0,f,d,0,NULL)
+#define pthread_join(t,s)       { WaitForSingleObject(t,INFINITE); \
+                                  CloseHandle(t); } 
+#define HAVE_PTHREAD 1
+
+#elif defined(SYS_BEOS)
 #include <kernel/OS.h>
 #define pthread_t               thread_id
-#define pthread_create(t,u,f,d) *(t)=spawn_thread(f,"",10,d)
+#define pthread_create(t,u,f,d) { *(t)=spawn_thread(f,"",10,d); \
+                                  resume_thread(*(t)); }
 #define pthread_join(t,s)       wait_for_thread(t,(long*)s)
-#else
+#define HAVE_PTHREAD 1
+
+#elif HAVE_PTHREAD
 #include <pthread.h>
 #endif
-#endif
 
 #include "common/common.h"
 #include "common/cpu.h"
@@ -376,6 +385,16 @@ static int x264_validate_parameters( x264_t *h )
     }
 #endif
 
+    if( !h->param.rc.b_cbr && h->param.rc.i_qp_constant == 0 )
+    {
+        h->mb.b_lossless = 1;
+        h->param.analyse.b_transform_8x8 = 0;
+        h->param.i_cqm_preset = X264_CQM_FLAT;
+        h->param.rc.f_ip_factor = 1;
+        h->param.rc.f_pb_factor = 1;
+        h->param.analyse.b_psnr = 0;
+    }
+
     h->param.i_frame_reference = x264_clip3( h->param.i_frame_reference, 1, 16 );
     if( h->param.i_keyint_max <= 0 )
         h->param.i_keyint_max = 1;
@@ -398,6 +417,9 @@ static int x264_validate_parameters( x264_t *h )
     if( h->param.i_threads > 1 && h->param.i_cabac_init_idc == -1 )
         h->param.i_cabac_init_idc = 0;
 
+    if( h->param.i_cqm_preset < X264_CQM_FLAT || h->param.i_cqm_preset > X264_CQM_CUSTOM )
+        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_HEX;
@@ -405,9 +427,14 @@ static int x264_validate_parameters( x264_t *h )
         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;
-    h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 5 );
+    h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 6 );
     if( !(h->param.analyse.inter & X264_ANALYSE_PSUB16x16) )
         h->param.analyse.inter &= ~X264_ANALYSE_PSUB8x8;
+    if( !h->param.analyse.b_transform_8x8 )
+    {
+        h->param.analyse.inter &= ~X264_ANALYSE_I8x8;
+        h->param.analyse.intra &= ~X264_ANALYSE_I8x8;
+    }
     h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_chroma_qp_offset, -12, 12);
     h->param.analyse.i_mv_range = x264_clip3(h->param.analyse.i_mv_range, 32, 2048);
 
@@ -426,7 +453,9 @@ static int x264_validate_parameters( x264_t *h )
 x264_t *x264_encoder_open   ( x264_param_t *param )
 {
     x264_t *h = x264_malloc( sizeof( x264_t ) );
-    int i, i_slice;
+    int i;
+
+    memset( h, 0, sizeof( x264_t ) );
 
     /* Create a copy of param */
     memcpy( &h->param, param, sizeof( x264_param_t ) );
@@ -437,6 +466,13 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
         return NULL;
     }
 
+    if( h->param.psz_cqm_file )
+        if( x264_cqm_parse_file( h, h->param.psz_cqm_file ) < 0 )
+        {
+            x264_free( h );
+            return NULL;
+        }
+
     if( h->param.rc.psz_stat_out )
         h->param.rc.psz_stat_out = strdup( h->param.rc.psz_stat_out );
     if( h->param.rc.psz_stat_in )
@@ -488,7 +524,9 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
 
     /* Init x264_t */
     h->out.i_nal = 0;
-    h->out.i_bitstream = 1000000; /* FIXME estimate max size (idth/height) */
+    h->out.i_bitstream = X264_MAX( 1000000, h->param.i_width * h->param.i_height * 1.7
+        * ( h->param.rc.b_cbr ? pow( 0.5, h->param.rc.i_qp_min )
+          : pow( 0.5, h->param.rc.i_qp_constant ) * X264_MAX( 1, h->param.rc.f_ip_factor )));
     h->out.p_bitstream = x264_malloc( h->out.i_bitstream );
 
     h->i_frame = 0;
@@ -500,6 +538,8 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
 
     h->pps = &h->pps_array[0];
     x264_pps_init( h->pps, 0, &h->param, h->sps);
+
+    x264_cqm_init( h );
     
     h->mb.i_mb_count = h->sps->i_mb_width * h->sps->i_mb_height;
 
@@ -536,6 +576,7 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
 
     /* init CPU functions */
     x264_predict_16x16_init( h->param.cpu, h->predict_16x16 );
+    x264_predict_8x8c_init( h->param.cpu, h->predict_8x8c );
     x264_predict_8x8_init( h->param.cpu, h->predict_8x8 );
     x264_predict_4x4_init( h->param.cpu, h->predict_4x4 );
 
@@ -544,25 +585,14 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
     x264_mc_init( h->param.cpu, &h->mc );
     x264_csp_init( h->param.cpu, h->param.i_csp, &h->csp );
 
+    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) );
+
     /* rate control */
     if( x264_ratecontrol_new( h ) < 0 )
         return NULL;
 
-    /* stat */
-    for( i_slice = 0; i_slice < 5; i_slice++ )
-    {
-        h->stat.i_slice_count[i_slice] = 0;
-        h->stat.i_slice_size[i_slice] = 0;
-        h->stat.i_slice_qp[i_slice] = 0;
-
-        h->stat.i_sqe_global[i_slice] = 0;
-        h->stat.f_psnr_average[i_slice] = 0.0;
-        h->stat.f_psnr_mean_y[i_slice] = h->stat.f_psnr_mean_u[i_slice] = h->stat.f_psnr_mean_v[i_slice] = 0.0;
-        
-        for( i = 0; i < 18; i++ )
-            h->stat.i_mb_count[i_slice][i] = 0;
-    }
-
     x264_log( h, X264_LOG_INFO, "using cpu capabilities %s%s%s%s%s%s\n",
              param->cpu&X264_CPU_MMX ? "MMX " : "",
              param->cpu&X264_CPU_MMXEXT ? "MMXEXT " : "",
@@ -594,6 +624,11 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
     if( h->sps->b_direct8x8_inference && h->param.i_bframe
         && h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_TEMPORAL )
         h->param.analyse.inter &= ~X264_ANALYSE_PSUB8x8;
+
+    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) );
+
     return x264_validate_parameters( h );
 }
 
@@ -889,6 +924,7 @@ static int x264_slice_write( x264_t *h )
     int i_skip;
     int mb_xy;
 
+    /* init stats */
     memset( &h->stat.frame, 0, sizeof(h->stat.frame) );
 
     /* Slice */
@@ -943,7 +979,7 @@ static int x264_slice_write( x264_t *h )
             {
                 if( h->sh.i_type != SLICE_TYPE_I )
                     x264_cabac_mb_skip( h, 0 );
-                x264_macroblock_write_cabac( h, &h->out.bs );
+                x264_macroblock_write_cabac( h, &h->cabac );
             }
         }
         else
@@ -971,6 +1007,11 @@ static int x264_slice_write( x264_t *h )
         x264_macroblock_cache_save( h );
 
         h->stat.frame.i_mb_count[h->mb.i_type]++;
+        if( h->mb.i_cbp_luma && !IS_INTRA(h->mb.i_type) )
+        {
+            h->stat.frame.i_mb_count_8x8dct[0] ++;
+            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) - mb_spos);
@@ -1321,9 +1362,10 @@ do_encode:
     if( i_slice_type == SLICE_TYPE_P && !h->param.rc.b_stat_read 
         && h->param.i_scenecut_threshold >= 0 )
     {
-        int i_mb_i = h->stat.frame.i_mb_count[I_4x4] + h->stat.frame.i_mb_count[I_16x16];
-        int i_mb_p = h->stat.frame.i_mb_count[P_L0] + h->stat.frame.i_mb_count[P_8x8];
-        int i_mb_s = h->stat.frame.i_mb_count[P_SKIP];
+        const int *mbs = h->stat.frame.i_mb_count;
+        int i_mb_i = mbs[I_16x16] + mbs[I_8x8] + mbs[I_4x4];
+        int i_mb_p = mbs[P_L0] + mbs[P_8x8];
+        int i_mb_s = mbs[P_SKIP];
         int i_mb   = h->sps->i_mb_width * h->sps->i_mb_height;
         int64_t i_inter_cost = h->stat.frame.i_inter_cost;
         int64_t i_intra_cost = h->stat.frame.i_intra_cost;
@@ -1361,8 +1403,8 @@ do_encode:
         {
             int b;
 
-            x264_log( h, X264_LOG_DEBUG, "scene cut at %d size=%d Icost:%.0f Pcost:%.0f ratio:%.3f bias=%.3f lastIDR:%d (I:%d P:%d Skip:%d)\n",
-                      h->fenc->i_frame, i_frame_size,
+            x264_log( h, X264_LOG_DEBUG, "scene cut at %d Icost:%.0f Pcost:%.0f ratio:%.3f bias=%.3f lastIDR:%d (I:%d P:%d S:%d)\n",
+                      h->fenc->i_frame,
                       (double)i_intra_cost, (double)i_inter_cost,
                       (double)i_inter_cost / i_intra_cost,
                       f_bias, i_gop_size,
@@ -1468,10 +1510,10 @@ do_encode:
     h->stat.i_slice_size[i_slice_type] += i_frame_size + NALU_OVERHEAD;
     h->stat.i_slice_qp[i_slice_type] += i_global_qp;
 
-    for( i = 0; i < 18; i++ )
-    {
+    for( i = 0; i < 19; i++ )
         h->stat.i_mb_count[h->sh.i_type][i] += h->stat.frame.i_mb_count[i];
-    }
+    for( i = 0; i < 2; i++ )
+        h->stat.i_mb_count_8x8dct[i] += h->stat.frame.i_mb_count_8x8dct[i];
 
     if( h->param.analyse.b_psnr )
     {
@@ -1500,14 +1542,13 @@ do_encode:
     }
     
     x264_log( h, X264_LOG_DEBUG,
-                  "frame=%4d QP=%i NAL=%d Slice:%c Poc:%-3d I4x4:%-4d I16x16:%-4d P:%-4d SKIP:%-4d size=%d bytes%s\n",
+                  "frame=%4d QP=%i NAL=%d Slice:%c Poc:%-3d I:%-4d P:%-4d SKIP:%-4d size=%d bytes%s\n",
               h->i_frame - 1,
               i_global_qp,
               i_nal_ref_idc,
               i_slice_type == SLICE_TYPE_I ? 'I' : (i_slice_type == SLICE_TYPE_P ? 'P' : 'B' ),
               frame_psnr->i_poc,
-              h->stat.frame.i_mb_count[I_4x4],
-              h->stat.frame.i_mb_count[I_16x16],
+              h->stat.frame.i_mb_count_i,
               h->stat.frame.i_mb_count_p,
               h->stat.frame.i_mb_count_skip,
               i_frame_size,
@@ -1516,12 +1557,12 @@ do_encode:
 
 #ifdef DEBUG_MB_TYPE
 {
-    static const char mb_chars[] = { 'i', 'I', 'C', 'P', '8', 'S',
+    static const char mb_chars[] = { 'i', 'i', 'I', 'C', 'P', '8', 'S',
         'D', '<', 'X', 'B', 'X', '>', 'B', 'B', 'B', 'B', '8', 'S' };
     int mb_xy;
     for( mb_xy = 0; mb_xy < h->sps->i_mb_width * h->sps->i_mb_height; mb_xy++ )
     {
-        if( h->mb.type[mb_xy] < 18 && h->mb.type[mb_xy] >= 0 )
+        if( h->mb.type[mb_xy] < 19 && h->mb.type[mb_xy] >= 0 )
             fprintf( stderr, "%c ", mb_chars[ h->mb.type[mb_xy] ] );
         else
             fprintf( stderr, "? " );
@@ -1609,8 +1650,9 @@ void    x264_encoder_close  ( x264_t *h )
         const int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_I];
         const double i_count = h->stat.i_slice_count[SLICE_TYPE_I] * h->mb.i_mb_count / 100.0;
         x264_log( h, X264_LOG_INFO,
-                  "slice I   Avg I4x4:%.1f%%  I16x16:%.1f%%\n",
+                  "slice I   Avg I4x4:%.1f%%  I8x8:%.1f%%  I16x16:%.1f%%\n",
                   i_mb_count[I_4x4]  / i_count,
+                  i_mb_count[I_8x8]  / i_count,
                   i_mb_count[I_16x16]/ i_count );
     }
     if( h->stat.i_slice_count[SLICE_TYPE_P] > 0 )
@@ -1618,8 +1660,9 @@ void    x264_encoder_close  ( x264_t *h )
         const int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_P];
         const double i_count = h->stat.i_slice_count[SLICE_TYPE_P] * h->mb.i_mb_count / 100.0;
         x264_log( h, X264_LOG_INFO,
-                  "slice P   Avg I4x4:%.1f%%  I16x16:%.1f%%  P:%.1f%%  P8x8:%.1f%%  PSKIP:%.1f%%\n",
+                  "slice P   Avg I4x4:%.1f%%  I8x8:%.1f%%  I16x16:%.1f%%  P:%.1f%%  P8x8:%.1f%%  PSKIP:%.1f%%\n",
                   i_mb_count[I_4x4]  / i_count,
+                  i_mb_count[I_8x8]  / i_count,
                   i_mb_count[I_16x16]/ i_count,
                   i_mb_count[P_L0]   / i_count,
                   i_mb_count[P_8x8]  / i_count,
@@ -1630,8 +1673,9 @@ void    x264_encoder_close  ( x264_t *h )
         const int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_B];
         const double i_count = h->stat.i_slice_count[SLICE_TYPE_B] * h->mb.i_mb_count / 100.0;
         x264_log( h, X264_LOG_INFO,
-                  "slice B   Avg I4x4:%.1f%%  I16x16:%.1f%%  P:%.1f%%  B:%.1f%%  B8x8:%.1f%%  DIRECT:%.1f%%  BSKIP:%.1f%%\n",
+                  "slice B   Avg I4x4:%.1f%%  I8x8:%.1f%%  I16x16:%.1f%%  P:%.1f%%  B:%.1f%%  B8x8:%.1f%%  DIRECT:%.1f%%  BSKIP:%.1f%%\n",
                   i_mb_count[I_4x4]    / i_count,
+                  i_mb_count[I_8x8]    / i_count,
                   i_mb_count[I_16x16]  / i_count,
                   (i_mb_count[B_L0_L0] + i_mb_count[B_L1_L1] + i_mb_count[B_L1_L0] + i_mb_count[B_L0_L1]) / i_count,
                   (i_mb_count[B_BI_BI] + i_mb_count[B_L0_BI] + i_mb_count[B_L1_BI] + i_mb_count[B_BI_L0] + i_mb_count[B_BI_L1]) / i_count,
@@ -1646,23 +1690,30 @@ void    x264_encoder_close  ( x264_t *h )
                             h->stat.i_slice_count[SLICE_TYPE_P] +
                             h->stat.i_slice_count[SLICE_TYPE_B];
         float fps = (float) h->param.i_fps_num / h->param.i_fps_den;
+#define SUM3(p) (p[SLICE_TYPE_I] + p[SLICE_TYPE_P] + p[SLICE_TYPE_B])
+#define SUM3b(p,o) (p[SLICE_TYPE_I][o] + p[SLICE_TYPE_P][o] + p[SLICE_TYPE_B][o])
+        float f_bitrate = fps * SUM3(h->stat.i_slice_size) / i_count / 125;
+
+        if( h->param.analyse.b_transform_8x8 )
+        {
+            int64_t i_i8x8 = SUM3b( h->stat.i_mb_count, I_8x8 );
+            int64_t i_intra = i_i8x8 + SUM3b( h->stat.i_mb_count, I_4x4 ) + SUM3b( h->stat.i_mb_count, I_16x16 );
+            x264_log( h, X264_LOG_INFO, "8x8 transform  intra:%.1f%%  inter:%.1f%%\n",
+                      100. * i_i8x8 / i_intra,
+                      100. * h->stat.i_mb_count_8x8dct[1] / h->stat.i_mb_count_8x8dct[0] );
+        }
 
         if( h->param.analyse.b_psnr )
             x264_log( h, X264_LOG_INFO,
                       "PSNR Mean Y:%5.2f U:%5.2f V:%5.2f Avg:%5.2f Global:%5.2f kb/s:%.1f\n",
-                      (h->stat.f_psnr_mean_y[SLICE_TYPE_I] + h->stat.f_psnr_mean_y[SLICE_TYPE_P] + h->stat.f_psnr_mean_y[SLICE_TYPE_B]) / i_count,
-                      (h->stat.f_psnr_mean_u[SLICE_TYPE_I] + h->stat.f_psnr_mean_u[SLICE_TYPE_P] + h->stat.f_psnr_mean_u[SLICE_TYPE_B]) / i_count,
-                      (h->stat.f_psnr_mean_v[SLICE_TYPE_I] + h->stat.f_psnr_mean_v[SLICE_TYPE_P] + h->stat.f_psnr_mean_v[SLICE_TYPE_B]) / i_count,
-
-                      (h->stat.f_psnr_average[SLICE_TYPE_I] + h->stat.f_psnr_average[SLICE_TYPE_P] + h->stat.f_psnr_average[SLICE_TYPE_B]) / i_count,
-
-                      x264_psnr( h->stat.i_sqe_global[SLICE_TYPE_I] + h->stat.i_sqe_global[SLICE_TYPE_P]+ h->stat.i_sqe_global[SLICE_TYPE_B],
-                                 i_count * i_yuv_size ),
-                      fps * 8*(h->stat.i_slice_size[SLICE_TYPE_I]+h->stat.i_slice_size[SLICE_TYPE_P]+h->stat.i_slice_size[SLICE_TYPE_B]) / i_count / 1000 );
+                      SUM3( h->stat.f_psnr_mean_y ) / i_count,
+                      SUM3( h->stat.f_psnr_mean_u ) / i_count,
+                      SUM3( h->stat.f_psnr_mean_v ) / i_count,
+                      SUM3( h->stat.f_psnr_average ) / i_count,
+                      x264_psnr( SUM3( h->stat.i_sqe_global ), i_count * i_yuv_size ),
+                      f_bitrate );
         else
-            x264_log( h, X264_LOG_INFO,
-                      "kb/s:%.1f\n",
-                      fps * 8*(h->stat.i_slice_size[SLICE_TYPE_I]+h->stat.i_slice_size[SLICE_TYPE_P]+h->stat.i_slice_size[SLICE_TYPE_B]) / i_count / 1000 );
+            x264_log( h, X264_LOG_INFO, "kb/s:%.1f\n", f_bitrate );
     }
 
     /* frames */