}
} while( !b_ok );
- /* In the standard, a P-frame's ref list is sorted by frame_num.
- * We use POC, but check whether explicit reordering is needed */
- h->b_ref_reorder[0] =
- h->b_ref_reorder[1] = 0;
- if( h->sh.i_type == SLICE_TYPE_P )
- {
- for( i = 0; i < h->i_ref0 - 1; i++ )
- if( h->fref0[i]->i_frame_num < h->fref0[i+1]->i_frame_num )
- {
- h->b_ref_reorder[0] = 1;
- break;
- }
- }
-
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
/* accumulate mb stats */
h->stat.frame.i_mb_count[h->mb.i_type]++;
- if( h->param.i_log_level >= X264_LOG_INFO )
+
+ if( !IS_INTRA(h->mb.i_type) && !IS_SKIP(h->mb.i_type) && !IS_DIRECT(h->mb.i_type) )
{
- if( !IS_SKIP(h->mb.i_type) && !IS_INTRA(h->mb.i_type) && !IS_DIRECT(h->mb.i_type) )
- {
- if( h->mb.i_partition != D_8x8 )
+ if( h->mb.i_partition != D_8x8 )
h->stat.frame.i_mb_partition[h->mb.i_partition] += 4;
else
for( i = 0; i < 4; i++ )
h->stat.frame.i_mb_partition[h->mb.i_sub_partition[i]] ++;
- if( h->param.i_frame_reference > 1 )
- for( i_list = 0; i_list <= (h->sh.i_type == SLICE_TYPE_B); i_list++ )
- for( i = 0; i < 4; i++ )
- {
- i_ref = h->mb.cache.ref[i_list][ x264_scan8[4*i] ];
- if( i_ref >= 0 )
- h->stat.frame.i_mb_count_ref[i_list][i_ref] ++;
- }
- }
+ if( h->param.i_frame_reference > 1 )
+ for( i_list = 0; i_list <= (h->sh.i_type == SLICE_TYPE_B); i_list++ )
+ for( i = 0; i < 4; i++ )
+ {
+ i_ref = h->mb.cache.ref[i_list][ x264_scan8[4*i] ];
+ if( i_ref >= 0 )
+ h->stat.frame.i_mb_count_ref[i_list][i_ref] ++;
+ }
+ }
+
+ if( h->param.i_log_level >= X264_LOG_INFO )
+ {
if( h->mb.i_cbp_luma || h->mb.i_cbp_chroma )
{
int cbpsum = (h->mb.i_cbp_luma&1) + ((h->mb.i_cbp_luma>>1)&1)
x264_picture_t *pic_out )
{
x264_t *thread_current, *thread_prev, *thread_oldest;
- int i_nal_type;
+ int i_nal_type, i;
int i_nal_ref_idc;
int i_global_qp;
h->out.i_nal = 0;
bs_init( &h->out.bs, h->out.p_bitstream, h->out.i_bitstream );
- if(h->param.b_aud){
+ if( h->param.b_aud )
+ {
int pic_type;
- if(h->sh.i_type == SLICE_TYPE_I)
+ if( h->sh.i_type == SLICE_TYPE_I )
pic_type = 0;
- else if(h->sh.i_type == SLICE_TYPE_P)
+ else if( h->sh.i_type == SLICE_TYPE_P )
pic_type = 1;
- else if(h->sh.i_type == SLICE_TYPE_B)
+ else if( h->sh.i_type == SLICE_TYPE_B )
pic_type = 2;
else
pic_type = 7;
- x264_nal_start(h, NAL_AUD, NAL_PRIORITY_DISPOSABLE);
- bs_write(&h->out.bs, 3, pic_type);
- bs_rbsp_trailing(&h->out.bs);
+ x264_nal_start( h, NAL_AUD, NAL_PRIORITY_DISPOSABLE );
+ bs_write( &h->out.bs, 3, pic_type );
+ bs_rbsp_trailing( &h->out.bs );
if( x264_nal_end( h ) )
return -1;
}
pic_out->i_qpplus1 =
h->fdec->i_qpplus1 = i_global_qp + 1;
+ if( h->param.rc.b_stat_read && h->sh.i_type != SLICE_TYPE_I )
+ x264_reference_build_list_optimal( h );
+
+ /* Check to see whether we have chosen a reference list ordering different
+ * from the standard's default. */
+ h->b_ref_reorder[0] =
+ h->b_ref_reorder[1] = 0;
+ for( i = 0; i < h->i_ref0 - 1; i++ )
+ /* P and B-frames use different default orders. */
+ if( h->sh.i_type == SLICE_TYPE_P ? h->fref0[i]->i_frame_num < h->fref0[i+1]->i_frame_num
+ : h->fref0[i]->i_poc < h->fref0[i+1]->i_poc )
+ {
+ h->b_ref_reorder[0] = 1;
+ break;
+ }
+
/* ------------------------ Create slice header ----------------------- */
x264_slice_init( h, i_nal_type, i_global_qp );
#include "common/common.h"
#include "common/cpu.h"
#include "ratecontrol.h"
+#include "me.h"
typedef struct
{
int s_count;
float blurred_complexity;
char direct_mode;
+ int refcount[16];
+ int refs;
} ratecontrol_entry_t;
typedef struct
return -1;
}
+int x264_reference_build_list_optimal( x264_t *h )
+{
+ ratecontrol_entry_t *rce = h->rc->rce;
+ x264_frame_t *frames[16];
+ int ref, i;
+
+ if( rce->refs != h->i_ref0 )
+ return -1;
+
+ memcpy( frames, h->fref0, sizeof(frames) );
+
+ /* For now don't reorder ref 0; it seems to lower quality
+ in most cases due to skips. */
+ for( ref = 1; ref < h->i_ref0; ref++ )
+ {
+ int max = -1;
+ int bestref = 1;
+ for( i = 1; i < h->i_ref0; i++ )
+ /* Favor lower POC as a tiebreaker. */
+ COPY2_IF_GT( max, rce->refcount[i], bestref, i );
+ rce->refcount[bestref] = -1;
+ h->fref0[ref] = frames[bestref];
+ }
+
+ return 0;
+}
+
static char *x264_strcat_filename( char *input, char *suffix )
{
char *output = x264_malloc( strlen( input ) + strlen( suffix ) + 1 );
int e;
char *next;
float qp;
+ int ref;
next= strchr(p, ';');
if(next)
&rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count,
&rce->s_count, &rce->direct_mode);
+ p = strstr( p, "ref:" );
+ if( !p )
+ goto parse_error;
+ p += 4;
+ for( ref = 0; ref < 16; ref++ )
+ {
+ if( sscanf( p, " %d", &rce->refcount[ref] ) != 1 )
+ break;
+ p = strchr( p+1, ' ' );
+ if( !p )
+ goto parse_error;
+ }
+ rce->refs = ref;
+
switch(pict_type)
{
case 'I': rce->kept_as_ref = 1;
}
if(e < 10)
{
+parse_error:
x264_log(h, X264_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);
return -1;
}
dir_avg>0 ? 's' : dir_avg<0 ? 't' : '-' )
: '-';
if( fprintf( rc->p_stat_file_out,
- "in:%d out:%d type:%c q:%.2f tex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c;\n",
+ "in:%d out:%d type:%c q:%.2f tex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c ref:",
h->fenc->i_frame, h->i_frame,
c_type, rc->qpa_rc,
h->stat.frame.i_tex_bits,
h->stat.frame.i_mb_count_p,
h->stat.frame.i_mb_count_skip,
c_direct) < 0 )
- goto fail;
+ goto fail;
+
+ for( i = 0; i < h->i_ref0; i++ )
+ {
+ int refcount = h->param.b_interlaced ? h->stat.frame.i_mb_count_ref[0][i*2]
+ + h->stat.frame.i_mb_count_ref[0][i*2+1] :
+ h->stat.frame.i_mb_count_ref[0][i];
+ if( fprintf( rc->p_stat_file_out, "%d ", refcount ) < 0 )
+ goto fail;
+ }
+
+ if( fprintf( rc->p_stat_file_out, ";\n" ) < 0 )
+ goto fail;
/* Don't re-write the data in multi-pass mode. */
if( h->param.rc.b_mb_tree && h->fenc->b_kept_as_ref && !h->param.rc.b_stat_read )