#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"
}
#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;
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;
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);
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 ) );
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 )
/* 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;
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;
/* 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 );
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 " : "",
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 );
}
int i_skip;
int mb_xy;
+ /* init stats */
memset( &h->stat.frame, 0, sizeof(h->stat.frame) );
/* Slice */
{
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
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);
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;
{
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,
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 )
{
}
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,
#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, "? " );
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 )
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,
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,
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 */