* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
-#include <stdio.h>
-#include <string.h>
#include <math.h>
#include "common/common.h"
#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
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 */
if( h->param.i_threads == 0 )
h->param.i_threads = x264_cpu_num_processors() * 3/2;
h->param.i_threads = x264_clip3( h->param.i_threads, 1, X264_THREAD_MAX );
- h->param.i_threads = X264_MIN( h->param.i_threads, 1 + (h->param.i_height >> h->param.b_interlaced) / (X264_THREAD_HEIGHT + 16) ); // FIXME exact limit?
if( h->param.i_threads > 1 )
{
#ifndef HAVE_PTHREAD
x264_log( h, X264_LOG_WARNING, "not compiled with pthread support!\n");
h->param.i_threads = 1;
#else
- if( h->param.analyse.i_me_method == X264_ME_ESA )
- {
- x264_log( h, X264_LOG_WARNING, "threads are not yet compatible with ESA\n");
- h->param.analyse.i_me_method = X264_ME_UMH;
- }
if( h->param.i_scenecut_threshold >= 0 )
h->param.b_pre_scenecut = 1;
#endif
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;
if( h->param.rc.i_rc_method < 0 || h->param.rc.i_rc_method > 2 )
{
- x264_log( h, X264_LOG_ERROR, "invalid RC method\n" );
+ x264_log( h, X264_LOG_ERROR, "no ratecontrol method specified\n" );
return -1;
}
h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, 0, 51 );
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 )
+ {
+ float qp_p = h->param.rc.i_qp_constant;
+ float qp_i = qp_p - 6*log(h->param.rc.f_ip_factor)/log(2);
+ float qp_b = qp_p + 6*log(h->param.rc.f_pb_factor)/log(2);
+ h->param.rc.i_qp_min = x264_clip3( (int)(X264_MIN3( qp_p, qp_i, qp_b )), 0, 51 );
+ h->param.rc.i_qp_max = x264_clip3( (int)(X264_MAX3( qp_p, qp_i, qp_b ) + .999), 0, 51 );
}
- if( ( h->param.i_width % 16 || h->param.i_height % 16 ) && !h->mb.b_lossless )
+ if( ( h->param.i_width % 16 || h->param.i_height % 16 )
+ && h->param.i_height != 1080 && !h->mb.b_lossless )
{
+ // There's nothing special about 1080 in that the warning still applies to it,
+ // but chances are the user can't help it if his content is already 1080p,
+ // so there's no point in warning in that case.
x264_log( h, X264_LOG_WARNING,
"width or height not divisible by 16 (%dx%d), compression will suffer.\n",
h->param.i_width, h->param.i_height );
h->mb.b_direct_auto_write = h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO
&& h->param.i_bframe
&& ( h->param.rc.b_stat_write || !h->param.rc.b_stat_read );
+ if( h->param.i_scenecut_threshold < 0 )
+ h->param.b_pre_scenecut = 0;
h->param.i_deblocking_filter_alphac0 = x264_clip3( h->param.i_deblocking_filter_alphac0, -6, 6 );
h->param.i_deblocking_filter_beta = x264_clip3( h->param.i_deblocking_filter_beta, -6, 6 );
h->param.analyse.i_luma_deadzone[0] = x264_clip3( h->param.analyse.i_luma_deadzone[0], 0, 32 );
h->param.analyse.i_luma_deadzone[1] = x264_clip3( h->param.analyse.i_luma_deadzone[1], 0, 32 );
- h->mb.i_luma_deadzone[0] = 32 - h->param.analyse.i_luma_deadzone[0];
- h->mb.i_luma_deadzone[1] = 32 - h->param.analyse.i_luma_deadzone[1];
h->param.i_cabac_init_idc = x264_clip3( h->param.i_cabac_init_idc, 0, 2 );
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;
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 );
{
if( h->param.analyse.i_mv_range <= 0 )
h->param.analyse.i_mv_range = l->mv_range;
else
- h->param.analyse.i_mv_range = x264_clip3(h->param.analyse.i_mv_range, 32, 2048);
+ h->param.analyse.i_mv_range = x264_clip3(h->param.analyse.i_mv_range, 32, 512);
if( h->param.analyse.i_direct_8x8_inference < 0 )
h->param.analyse.i_direct_8x8_inference = l->direct8x8;
}
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) );
}
/****************************************************************************
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 ) );
x264_validate_levels( h );
- x264_cqm_init( h );
+ if( x264_cqm_init( h ) < 0 )
+ {
+ x264_free( h );
+ return NULL;
+ }
h->mb.i_mb_count = h->sps->i_mb_width * h->sps->i_mb_height;
h->frames.i_delay = h->param.i_bframe + h->param.i_threads - 1;
h->frames.i_max_ref0 = h->param.i_frame_reference;
h->frames.i_max_ref1 = h->sps->vui.i_num_reorder_frames;
- h->frames.i_max_dpb = h->sps->vui.i_max_dec_frame_buffering + 1;
+ h->frames.i_max_dpb = h->sps->vui.i_max_dec_frame_buffering;
h->frames.b_have_lowres = !h->param.rc.b_stat_read
&& ( h->param.rc.i_rc_method == X264_RC_ABR
|| h->param.rc.i_rc_method == X264_RC_CRF
- || h->param.b_bframe_adaptive );
+ || 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;
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\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_3DNOW ? "3DNow! " : "",
- param->cpu&X264_CPU_ALTIVEC ? "Altivec " : "" );
+ 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 * 1.7
- * ( h->param.rc.i_rc_method == X264_RC_ABR ? 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.i_bitstream = X264_MAX( 1000000, h->param.i_width * h->param.i_height * 4
+ * ( h->param.rc.i_rc_method == X264_RC_ABR ? pow( 0.95, h->param.rc.i_qp_min )
+ : pow( 0.95, h->param.rc.i_qp_constant ) * X264_MAX( 1, h->param.rc.f_ip_factor )));
h->thread[0] = h;
h->i_thread_num = 0;
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
return NULL;
}
}
-#endif
return h;
}
#define COPY(var) h->param.var = param->var
COPY( i_frame_reference ); // but never uses more refs than initially specified
COPY( i_bframe_bias );
- COPY( i_scenecut_threshold );
+ if( h->param.i_scenecut_threshold >= 0 && param->i_scenecut_threshold >= 0 )
+ COPY( i_scenecut_threshold ); // can't turn it on or off, only vary the threshold
COPY( b_deblocking_filter );
COPY( i_deblocking_filter_alphac0 );
COPY( i_deblocking_filter_beta );
COPY( analyse.b_dct_decimate );
COPY( analyse.b_fast_pskip );
COPY( analyse.b_mixed_references );
-#undef COPY
-
+ // can only twiddle these if they were enabled to begin with:
if( h->pps->b_transform_8x8_mode )
- h->param.analyse.b_transform_8x8 = param->analyse.b_transform_8x8;
+ COPY( analyse.b_transform_8x8 );
+ if( h->frames.i_max_ref1 > 1 )
+ COPY( b_bframe_pyramid );
+#undef COPY
mbcmp_init( h );
nal->i_ref_idc = i_ref_idc;
nal->i_type = i_type;
- bs_align_0( &h->out.bs ); /* not needed */
-
nal->i_payload= 0;
- nal->p_payload= &h->out.p_bitstream[bs_pos( &h->out.bs) / 8];
+ nal->p_payload= &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8];
}
static void x264_nal_end( x264_t *h )
{
x264_nal_t *nal = &h->out.nal[h->out.i_nal];
-
- bs_align_0( &h->out.bs ); /* not needed */
-
- nal->i_payload = &h->out.p_bitstream[bs_pos( &h->out.bs)/8] - nal->p_payload;
-
+ nal->i_payload = &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8] - nal->p_payload;
h->out.i_nal++;
}
/* now set output*/
*pi_nal = h->out.i_nal;
*pp_nal = &h->out.nal[0];
+ h->out.i_nal = 0;
return 0;
}
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;
}
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 )
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 );
}
- if( h->param.i_threads > 1 )
+ if( h->param.i_threads > 1 && h->fdec->b_kept_as_ref )
{
- h->fdec->i_lines_completed = mb_y*16 + (b_end ? 10000 : -(X264_THREAD_HEIGHT << h->sh.b_mbaff));
- x264_frame_cond_broadcast( h->fdec );
+ x264_frame_cond_broadcast( h->fdec, mb_y*16 + (b_end ? 10000 : -(X264_THREAD_HEIGHT << h->sh.b_mbaff)) );
}
}
static inline void x264_reference_reset( x264_t *h )
{
while( h->frames.reference[0] )
- x264_frame_push_unused( h, x264_frame_shift( h->frames.reference ) );
+ x264_frame_push_unused( h, x264_frame_pop( h->frames.reference ) );
h->fdec->i_poc =
h->fenc->i_poc = 0;
}
x264_macroblock_slice_init( h );
}
-static int x264_slice_write( x264_t *h )
+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 */
/* init cabac */
x264_cabac_context_init( &h->cabac, h->sh.i_type, h->sh.i_qp, h->sh.i_cabac_init_idc );
- x264_cabac_encode_init ( &h->cabac, &h->out.bs );
+ x264_cabac_encode_init ( &h->cabac, h->out.bs.p, h->out.bs.p_end );
}
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);
+ int mb_spos = bs_pos(&h->out.bs) + x264_cabac_pos(&h->cabac);
if( i_mb_x == 0 )
x264_fdec_filter_row( h, i_mb_y );
* 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 );
x264_macroblock_write_cavlc( h, &h->out.bs );
}
}
- TIMER_STOP( i_mtime_write );
#if VISUALIZE
if( h->param.b_visualize )
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);
+ 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
- h->stat.frame.i_itex_bits
- h->stat.frame.i_ptex_bits
- h->stat.frame.i_hdr_bits;
-
- return 0;
}
static void x264_thread_sync_context( x264_t *dst, x264_t *src )
x264_visualize_init( h );
#endif
- x264_slice_write( 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 )
*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 )
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 )
{
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 */
/* ------------------- 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 */
/* Write frame */
if( h->param.i_threads > 1 )
{
- pthread_create( &h->thread_handle, NULL, (void*)x264_slices_write, h );
+ x264_pthread_create( &h->thread_handle, NULL, (void*)x264_slices_write, h );
h->b_thread_active = 1;
}
else
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
if( h->b_thread_active )
{
- pthread_join( h->thread_handle, NULL );
+ x264_pthread_join( h->thread_handle, NULL );
h->b_thread_active = 0;
}
if( !h->out.i_nal )
/* ---------------------- 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] );
/* 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];
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 );
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,
}
#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 );
}
/****************************************************************************
****************************************************************************/
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;
{
// don't strictly have to wait for the other threads, but it's simpler than cancelling them
if( h->thread[i]->b_thread_active )
- pthread_join( h->thread[i]->thread_handle, NULL );
+ 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++ )
{
"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,
"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 );
}
}