Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/common/common.c b/common/common.c
- index a9e1c73..dd5bb07 100644
- --- a/common/common.c
- +++ b/common/common.c
- @@ -87,6 +87,7 @@ void x264_param_default( x264_param_t *param )
- param->i_bframe_bias = 0;
- param->i_bframe_pyramid = X264_B_PYRAMID_NORMAL;
- param->b_interlaced = 0;
- + param->b_field_encode = 0;
- param->b_constrained_intra = 0;
- param->b_deblocking_filter = 1;
- @@ -798,13 +799,26 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
- OPT("cabac-idc")
- p->i_cabac_init_idc = atoi(value);
- OPT("interlaced")
- + {
- p->b_interlaced = atobool(value);
- + p->b_field_encode = 0;
- + }
- + OPT("field-encode")
- + {
- + p->b_interlaced = 0;
- + p->b_field_encode = atobool(value);
- + }
- OPT("tff")
- - p->b_interlaced = p->b_tff = atobool(value);
- + {
- + p->b_tff = atobool(value);
- + if( !p->b_field_encode )
- + p->b_interlaced = 1;
- + }
- OPT("bff")
- {
- - p->b_interlaced = atobool(value);
- - p->b_tff = !p->b_interlaced;
- + p->b_tff = !atobool(value);
- + if( !p->b_field_encode )
- + p->b_interlaced = 1;
- }
- OPT("constrained-intra")
- p->b_constrained_intra = atobool(value);
- diff --git a/common/common.h b/common/common.h
- index 76ae8a3..ef2395b 100644
- --- a/common/common.h
- +++ b/common/common.h
- @@ -81,8 +81,8 @@ do {\
- #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
- -#define X264_BFRAME_MAX 16
- -#define X264_REF_MAX 16
- +#define X264_BFRAME_MAX 32
- +#define X264_REF_MAX 32
- #define X264_THREAD_MAX 128
- #define X264_LOOKAHEAD_THREAD_MAX 16
- #define X264_PCM_COST (FRAME_SIZE(256*BIT_DEPTH)+16)
- @@ -125,11 +125,17 @@ do {\
- #if HAVE_INTERLACED
- # define MB_INTERLACED h->mb.b_interlaced
- # define SLICE_MBAFF h->sh.b_mbaff
- +# define SLICE_FIELD h->sh.b_field_pic
- # define PARAM_INTERLACED h->param.b_interlaced
- +# define PARAM_FIELD_ENCODE h->param.b_field_encode
- +# define MB_MBAFF_FIELD (SLICE_MBAFF & MB_INTERLACED)
- #else
- # define MB_INTERLACED 0
- # define SLICE_MBAFF 0
- +# define SLICE_FIELD 0
- # define PARAM_INTERLACED 0
- +# define PARAM_FIELD_ENCODE 0
- +# define MB_MBAFF_FIELD 0
- #endif
- #ifdef CHROMA_FORMAT
- @@ -440,6 +446,7 @@ typedef struct x264_lookahead_t
- int i_last_keyframe;
- int i_slicetype_length;
- x264_frame_t *last_nonb;
- + x264_frame_t *penultimate_nonb;
- x264_pthread_t thread_handle;
- x264_sync_frame_list_t ifbuf;
- x264_sync_frame_list_t next;
- @@ -887,6 +894,7 @@ struct x264_t
- int ref_blind_dupe; /* The index of the blind reference frame duplicate. */
- int8_t deblock_ref_table[X264_REF_MAX*2+2];
- #define deblock_ref_table(x) h->mb.deblock_ref_table[(x)+2]
- + int i_mvy_offset[2][X264_REF_MAX];
- } mb;
- /* rate control encoding only */
- diff --git a/common/deblock.c b/common/deblock.c
- index 382eb72..ae62b8e 100644
- --- a/common/deblock.c
- +++ b/common/deblock.c
- @@ -343,8 +343,8 @@ static ALWAYS_INLINE void x264_macroblock_cache_load_neighbours_deblock( x264_t
- h->mb.i_neighbour = 0;
- h->mb.i_mb_xy = mb_y * h->mb.i_mb_stride + mb_x;
- - h->mb.b_interlaced = PARAM_INTERLACED && h->mb.field[h->mb.i_mb_xy];
- - h->mb.i_mb_top_y = mb_y - (1 << MB_INTERLACED);
- + h->mb.b_interlaced = PARAM_FIELD_ENCODE || (PARAM_INTERLACED && h->mb.field[h->mb.i_mb_xy]);
- + h->mb.i_mb_top_y = mb_y - (1 << MB_MBAFF_FIELD);
- h->mb.i_mb_top_xy = mb_x + h->mb.i_mb_stride*h->mb.i_mb_top_y;
- h->mb.i_mb_left_xy[1] =
- h->mb.i_mb_left_xy[0] = h->mb.i_mb_xy - 1;
- @@ -370,14 +370,14 @@ static ALWAYS_INLINE void x264_macroblock_cache_load_neighbours_deblock( x264_t
- if( mb_x > 0 && (deblock_on_slice_edges ||
- h->mb.slice_table[h->mb.i_mb_left_xy[0]] == h->mb.slice_table[h->mb.i_mb_xy]) )
- h->mb.i_neighbour |= MB_LEFT;
- - if( mb_y > MB_INTERLACED && (deblock_on_slice_edges
- + if( mb_y > MB_MBAFF_FIELD && (deblock_on_slice_edges
- || h->mb.slice_table[h->mb.i_mb_top_xy] == h->mb.slice_table[h->mb.i_mb_xy]) )
- h->mb.i_neighbour |= MB_TOP;
- }
- void x264_frame_deblock_row( x264_t *h, int mb_y )
- {
- - int b_interlaced = SLICE_MBAFF;
- + int b_mbaff = SLICE_MBAFF;
- int a = h->sh.i_alpha_c0_offset - QP_BD_OFFSET;
- int b = h->sh.i_beta_offset - QP_BD_OFFSET;
- int qp_thresh = 15 - X264_MIN( a, b ) - X264_MAX( 0, h->pps->i_chroma_qp_index_offset );
- @@ -387,7 +387,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
- int chroma_height = 16 >> CHROMA_V_SHIFT;
- intptr_t uvdiff = chroma444 ? h->fdec->plane[2] - h->fdec->plane[1] : 1;
- - for( int mb_x = 0; mb_x < h->mb.i_mb_width; mb_x += (~b_interlaced | mb_y)&1, mb_y ^= b_interlaced )
- + for( int mb_x = 0; mb_x < h->mb.i_mb_width; mb_x += (~b_mbaff | mb_y)&1, mb_y ^= b_mbaff )
- {
- x264_prefetch_fenc( h, h->fdec, mb_x, mb_y );
- x264_macroblock_cache_load_neighbours_deblock( h, mb_x, mb_y );
- @@ -400,14 +400,14 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
- pixel *pixy = h->fdec->plane[0] + 16*mb_y*stridey + 16*mb_x;
- pixel *pixuv = h->fdec->plane[1] + chroma_height*mb_y*strideuv + 16*mb_x;
- - if( mb_y & MB_INTERLACED )
- + if( mb_y & MB_MBAFF_FIELD )
- {
- pixy -= 15*stridey;
- pixuv -= (chroma_height-1)*strideuv;
- }
- - int stride2y = stridey << MB_INTERLACED;
- - int stride2uv = strideuv << MB_INTERLACED;
- + int stride2y = stridey << MB_MBAFF_FIELD;
- + int stride2uv = strideuv << MB_MBAFF_FIELD;
- int qp = h->mb.qp[mb_xy];
- int qpc = h->chroma_qp_table[qp];
- int first_edge_only = (h->mb.partition[mb_xy] == D_16x16 && !h->mb.cbp[mb_xy] && !intra_cur) || qp <= qp_thresh;
- @@ -446,7 +446,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
- if( h->mb.i_neighbour & MB_LEFT )
- {
- - if( b_interlaced && h->mb.field[h->mb.i_mb_left_xy[0]] != MB_INTERLACED )
- + if( b_mbaff && h->mb.field[h->mb.i_mb_left_xy[0]] != MB_INTERLACED )
- {
- int luma_qp[2];
- int chroma_qp[2];
- @@ -528,7 +528,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
- if( h->mb.i_neighbour & MB_TOP )
- {
- - if( b_interlaced && !(mb_y&1) && !MB_INTERLACED && h->mb.field[h->mb.i_mb_top_xy] )
- + if( b_mbaff && !(mb_y&1) && !MB_INTERLACED && h->mb.field[h->mb.i_mb_top_xy] )
- {
- int mbn_xy = mb_xy - 2 * h->mb.i_mb_stride;
- @@ -567,7 +567,7 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
- RESET_EFFECTIVE_QP(h->mb.i_mb_top_xy);
- }
- - if( (!b_interlaced || (!MB_INTERLACED && !h->mb.field[h->mb.i_mb_top_xy])) && intra_deblock )
- + if( (!b_mbaff || (!MB_INTERLACED && !h->mb.field[h->mb.i_mb_top_xy])) && intra_deblock && !SLICE_FIELD )
- {
- FILTER( _intra, 1, 0, qp_top, qpc_top );
- }
- diff --git a/common/frame.h b/common/frame.h
- index f95ffa9..e5fdbb1 100644
- --- a/common/frame.h
- +++ b/common/frame.h
- @@ -136,6 +136,7 @@ typedef struct x264_frame
- float f_weighted_cost_delta[X264_BFRAME_MAX+2];
- uint32_t i_pixel_sum[3];
- uint64_t i_pixel_ssd[3];
- + int b_ref_opp_field; /* set to one if field references field of opposite parity */
- /* hrd */
- x264_hrd_t hrd_timing;
- diff --git a/common/macroblock.c b/common/macroblock.c
- index 8494bfe..4c9cbc7 100644
- --- a/common/macroblock.c
- +++ b/common/macroblock.c
- @@ -53,8 +53,8 @@ static NOINLINE void x264_mb_mc_0xywh( x264_t *h, int x, int y, int width, int h
- {
- int v_shift = CHROMA_V_SHIFT;
- // Chroma in 4:2:0 is offset if MCing from a field of opposite parity
- - if( v_shift & MB_INTERLACED & i_ref )
- - mvy += (h->mb.i_mb_y & 1)*4 - 2;
- + if( v_shift & MB_INTERLACED )
- + mvy += h->mb.i_mvy_offset[0][i_ref];
- int offset = (4*FDEC_STRIDE>>v_shift)*y + 2*x;
- height = 4*height >> v_shift;
- @@ -91,8 +91,8 @@ static NOINLINE void x264_mb_mc_1xywh( x264_t *h, int x, int y, int width, int h
- else
- {
- int v_shift = CHROMA_V_SHIFT;
- - if( v_shift & MB_INTERLACED & i_ref )
- - mvy += (h->mb.i_mb_y & 1)*4 - 2;
- + if( v_shift & MB_INTERLACED )
- + mvy += h->mb.i_mvy_offset[1][i_ref];
- int offset = (4*FDEC_STRIDE>>v_shift)*y + 2*x;
- h->mc.mc_chroma( &h->mb.pic.p_fdec[1][offset],
- @@ -136,10 +136,11 @@ static NOINLINE void x264_mb_mc_01xywh( x264_t *h, int x, int y, int width, int
- else
- {
- int v_shift = CHROMA_V_SHIFT;
- - if( v_shift & MB_INTERLACED & i_ref0 )
- - mvy0 += (h->mb.i_mb_y & 1)*4 - 2;
- - if( v_shift & MB_INTERLACED & i_ref1 )
- - mvy1 += (h->mb.i_mb_y & 1)*4 - 2;
- + if( v_shift & MB_INTERLACED )
- + {
- + mvy0 += h->mb.i_mvy_offset[0][i_ref0];
- + mvy1 += h->mb.i_mvy_offset[1][i_ref1];
- + }
- h->mc.mc_chroma( tmp0, tmp0+8, 16, h->mb.pic.p_fref[0][i_ref0][4], h->mb.pic.i_stride[1],
- mvx0, 2*mvy0>>v_shift, 2*width, 4*height>>v_shift );
- @@ -254,7 +255,7 @@ int x264_macroblock_cache_allocate( x264_t *h )
- h->mb.i_b8_stride = h->mb.i_mb_width * 2;
- h->mb.i_b4_stride = h->mb.i_mb_width * 4;
- - h->mb.b_interlaced = PARAM_INTERLACED;
- + h->mb.b_interlaced = PARAM_INTERLACED || PARAM_FIELD_ENCODE;
- PREALLOC_INIT
- @@ -331,9 +332,12 @@ int x264_macroblock_cache_allocate( x264_t *h )
- for( int i = 0; i < 2; i++ )
- {
- - int i_refs = X264_MIN(X264_REF_MAX, (i ? 1 + !!h->param.i_bframe_pyramid : h->param.i_frame_reference) ) << PARAM_INTERLACED;
- + // FIXME this is probably wrong
- + int i_refs = X264_MIN(X264_REF_MAX, (i ? 1 + !!h->param.i_bframe_pyramid : h->param.i_frame_reference>>PARAM_FIELD_ENCODE) ) << PARAM_INTERLACED;
- if( h->param.analyse.i_weighted_pred == X264_WEIGHTP_SMART )
- i_refs = X264_MIN(X264_REF_MAX, i_refs + 1 + (BIT_DEPTH == 8)); //smart weights add two duplicate frames, one in >8-bit
- + if( PARAM_FIELD_ENCODE )
- + i_refs = X264_MIN(X264_REF_MAX, i_refs<<1);
- for( int j = !i; j < i_refs; j++ )
- {
- @@ -487,6 +491,21 @@ void x264_macroblock_slice_init( x264_t *h )
- h->fdec->inv_ref_poc[field] = (256 + delta/2) / delta;
- }
- + int cur_bottom = (h->fdec->i_frame & 1) ^ !h->param.b_tff;
- + for( int i = 0; i < h->i_ref[0]; i++ )
- + {
- + int ref_bottom = (h->fref[0][i]->i_frame & 1) ^ !h->param.b_tff;
- + h->mb.i_mvy_offset[0][i] = SLICE_MBAFF ? i&1 ? (h->mb.i_mb_y & 1)*4 - 2 : 0
- + : cur_bottom && !ref_bottom ? +2 : !cur_bottom && ref_bottom ? -2 : 0;
- + }
- + if( h->sh.i_type == SLICE_TYPE_B )
- + for( int i = 0; i < h->i_ref[1]; i++ )
- + {
- + int ref_bottom = (h->fref[1][i]->i_frame & 1) ^ !h->param.b_tff;
- + h->mb.i_mvy_offset[1][i] = SLICE_MBAFF ? i&1 ? (h->mb.i_mb_y & 1)*4 - 2 : 0
- + : cur_bottom && !ref_bottom ? +2 : !cur_bottom && ref_bottom ? -2 : 0;
- + }
- +
- h->mb.i_neighbour4[6] =
- h->mb.i_neighbour4[9] =
- h->mb.i_neighbour4[12] =
- @@ -1305,8 +1324,8 @@ static void ALWAYS_INLINE x264_macroblock_cache_load( x264_t *h, int mb_x, int m
- /* load skip */
- if( h->sh.i_type == SLICE_TYPE_B )
- {
- - h->mb.bipred_weight = h->mb.bipred_weight_buf[MB_INTERLACED][MB_INTERLACED&(mb_y&1)];
- - h->mb.dist_scale_factor = h->mb.dist_scale_factor_buf[MB_INTERLACED][MB_INTERLACED&(mb_y&1)];
- + h->mb.bipred_weight = h->mb.bipred_weight_buf[MB_MBAFF_FIELD][MB_MBAFF_FIELD&(mb_y&1)];
- + h->mb.dist_scale_factor = h->mb.dist_scale_factor_buf[MB_MBAFF_FIELD][MB_MBAFF_FIELD&(mb_y&1)];
- if( h->param.b_cabac )
- {
- uint8_t skipbp;
- diff --git a/common/mvpred.c b/common/mvpred.c
- index 745c8ea..b15907a 100644
- --- a/common/mvpred.c
- +++ b/common/mvpred.c
- @@ -187,8 +187,8 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h )
- int mb_xy = h->mb.i_mb_xy;
- int type_col[2] = { h->fref[1][0]->mb_type[mb_xy], h->fref[1][0]->mb_type[mb_xy] };
- int partition_col[2] = { h->fref[1][0]->mb_partition[mb_xy], h->fref[1][0]->mb_partition[mb_xy] };
- - int preshift = MB_INTERLACED;
- - int postshift = MB_INTERLACED;
- + int preshift = MB_MBAFF_FIELD;
- + int postshift = MB_MBAFF_FIELD;
- int offset = 1;
- int yshift = 1;
- h->mb.i_partition = partition_col[0];
- @@ -257,7 +257,7 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h )
- int i_part_8x8 = i_mb_8x8 + x8 + (ypart>>1) * h->mb.i_b8_stride;
- int i_ref1_ref = h->fref[1][0]->ref[0][i_part_8x8];
- - int i_ref = (map_col_to_list0(i_ref1_ref>>preshift) << postshift) + (offset&i_ref1_ref&MB_INTERLACED);
- + int i_ref = (map_col_to_list0(i_ref1_ref>>preshift) << postshift) + (offset&i_ref1_ref&MB_MBAFF_FIELD);
- if( i_ref >= 0 )
- {
- diff --git a/common/set.h b/common/set.h
- index 6fb7aba..da908ba 100644
- --- a/common/set.h
- +++ b/common/set.h
- @@ -157,6 +157,7 @@ typedef struct
- int b_qpprime_y_zero_transform_bypass;
- int i_chroma_format_idc;
- + int b_half_height;
- } x264_sps_t;
- diff --git a/encoder/analyse.c b/encoder/analyse.c
- index 9131d3d..cd58250 100644
- --- a/encoder/analyse.c
- +++ b/encoder/analyse.c
- @@ -3986,8 +3986,8 @@ static void x264_analyse_update_cache( x264_t *h, x264_mb_analysis_t *a )
- int ref = h->mb.cache.ref[l][x264_scan8[0]];
- if( ref < 0 )
- continue;
- - completed = h->fref[l][ ref >> MB_INTERLACED ]->orig->i_lines_completed;
- - if( (h->mb.cache.mv[l][x264_scan8[15]][1] >> (2 - MB_INTERLACED)) + h->mb.i_mb_y*16 > completed )
- + completed = h->fref[l][ ref >> MB_MBAFF_FIELD ]->orig->i_lines_completed;
- + if( (h->mb.cache.mv[l][x264_scan8[15]][1] >> (2 - MB_MBAFF_FIELD)) + h->mb.i_mb_y*16 > completed )
- {
- x264_log( h, X264_LOG_WARNING, "internal error (MV out of thread range)\n");
- x264_log( h, X264_LOG_DEBUG, "mb type: %d \n", h->mb.i_type);
- diff --git a/encoder/encoder.c b/encoder/encoder.c
- index 1ea341b..559e9d9 100644
- --- a/encoder/encoder.c
- +++ b/encoder/encoder.c
- @@ -87,11 +87,17 @@ static void x264_frame_dump( x264_t *h )
- x264_threadpool_wait_all( h );
- /* Write the frame in display order */
- - int frame_size = FRAME_SIZE( h->param.i_height * h->param.i_width * sizeof(pixel) );
- - fseek( f, (uint64_t)h->fdec->i_frame * frame_size, SEEK_SET );
- + int frame_size = FRAME_SIZE( h->param.i_height * (1+PARAM_FIELD_ENCODE) * h->param.i_width * sizeof(pixel) );
- + fseek( f, (uint64_t)(h->fdec->i_frame >> PARAM_FIELD_ENCODE) * frame_size, SEEK_SET );
- + if( PARAM_FIELD_ENCODE && h->sh.b_bottom_field )
- + fseek( f, (uint64_t)h->param.i_width, SEEK_CUR );
- for( int p = 0; p < (CHROMA444 ? 3 : 1); p++ )
- for( int y = 0; y < h->param.i_height; y++ )
- + {
- fwrite( &h->fdec->plane[p][y*h->fdec->i_stride[p]], sizeof(pixel), h->param.i_width, f );
- + if( PARAM_FIELD_ENCODE )
- + fseek( f, (uint64_t)h->param.i_width, SEEK_CUR );
- + }
- if( !CHROMA444 )
- {
- int cw = h->param.i_width>>1;
- @@ -101,8 +107,26 @@ static void x264_frame_dump( x264_t *h )
- {
- pixel *planev = planeu + cw*ch + 16;
- h->mc.plane_copy_deinterleave( planeu, cw, planev, cw, h->fdec->plane[1], h->fdec->i_stride[1], cw, ch );
- - fwrite( planeu, 1, cw*ch*sizeof(pixel), f );
- - fwrite( planev, 1, cw*ch*sizeof(pixel), f );
- + if( PARAM_FIELD_ENCODE )
- + {
- + if( h->sh.b_bottom_field )
- + fseek( f, (uint64_t)(-(h->param.i_width>>1)), SEEK_CUR );
- + for( int y = 0; y < ch; y++ )
- + {
- + fwrite( &planeu[y*cw], sizeof(pixel), cw, f );
- + fseek( f, (uint64_t)cw, SEEK_CUR );
- + }
- + for( int y = 0; y < ch; y++ )
- + {
- + fwrite( &planev[y*cw], sizeof(pixel), cw, f );
- + fseek( f, (uint64_t)cw, SEEK_CUR );
- + }
- + }
- + else
- + {
- + fwrite( planeu, 1, cw*ch*sizeof(pixel), f );
- + fwrite( planev, 1, cw*ch*sizeof(pixel), f );
- + }
- x264_free( planeu );
- }
- }
- @@ -127,8 +151,8 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
- sh->i_frame_num = i_frame;
- sh->b_mbaff = PARAM_INTERLACED;
- - sh->b_field_pic = 0; /* no field support for now */
- - sh->b_bottom_field = 0; /* not yet used */
- + sh->b_field_pic = PARAM_FIELD_ENCODE;
- + sh->b_bottom_field = h->fenc->i_pic_struct == PIC_STRUCT_BOTTOM;
- sh->i_idr_pic_id = i_idr_pic_id;
- @@ -173,13 +197,23 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
- {
- if( sh->b_ref_pic_list_reordering[list] )
- {
- - int pred_frame_num = i_frame;
- + int pred_frame_num, pic_num;
- + pred_frame_num = PARAM_FIELD_ENCODE ? 2 * sh->i_frame_num + 1 : i_frame;
- +
- for( int i = 0; i < h->i_ref[list]; i++ )
- {
- - int diff = h->fref[list][i]->i_frame_num - pred_frame_num;
- + if( PARAM_FIELD_ENCODE )
- + {
- + int same_parity = ((h->fenc->i_frame ^ h->fref[list][i]->i_frame) & 1) ^ 1;
- + pic_num = 2 * h->fref[list][i]->i_frame_num + same_parity;
- + }
- + else
- + pic_num = h->fref[list][i]->i_frame_num;
- +
- + int diff = pic_num - pred_frame_num;
- sh->ref_pic_list_order[list][i].idc = ( diff > 0 );
- sh->ref_pic_list_order[list][i].arg = (abs(diff) - 1) & ((1 << sps->i_log2_max_frame_num) - 1);
- - pred_frame_num = h->fref[list][i]->i_frame_num;
- + pred_frame_num = pic_num;
- }
- }
- }
- @@ -405,6 +439,19 @@ static void x264_encoder_thread_init( x264_t *h )
- }
- #endif
- +static int x264_diff_pic_num( x264_t *h, x264_frame_t *src, x264_frame_t *ref )
- +{
- + if( PARAM_FIELD_ENCODE )
- + {
- + int cur_pic_num = 2 * src->i_frame_num + 1;
- + int same_parity = ((src->i_frame ^ ref->i_frame) & 1) ^ 1;
- + int ref_pic_num = 2 * ref->i_frame_num + same_parity;
- + return cur_pic_num - ref_pic_num;
- + }
- + else
- + return src->i_frame_num - ref->i_frame_num;
- +}
- +
- /****************************************************************************
- *
- ****************************************************************************
- @@ -454,8 +501,14 @@ static int x264_validate_parameters( x264_t *h, int b_open )
- #if HAVE_INTERLACED
- h->param.b_interlaced = !!PARAM_INTERLACED;
- + h->param.b_field_encode = !!PARAM_FIELD_ENCODE;
- + if( h->param.b_interlaced && h->param.b_field_encode )
- + {
- + x264_log( h, X264_LOG_ERROR, "MBAFF and field encode is invalid\n" );
- + return -1;
- + }
- #else
- - if( h->param.b_interlaced )
- + if( h->param.b_interlaced || h->param.b_field_encode )
- {
- x264_log( h, X264_LOG_ERROR, "not compiled with interlaced support\n" );
- return -1;
- @@ -584,6 +637,17 @@ static int x264_validate_parameters( x264_t *h, int b_open )
- }
- h->param.i_frame_packing = x264_clip3( h->param.i_frame_packing, -1, 5 );
- + if( h->param.i_frame_packing == 5 && PARAM_FIELD_ENCODE )
- + {
- + x264_log( h, X264_LOG_ERROR, "Frame packing 5 not supported with PAFF\n" );
- + return -1;
- + }
- +
- + if( PARAM_FIELD_ENCODE && h->param.i_bframe > 0 )
- + {
- + x264_log( h, X264_LOG_WARNING, "B-frames not supported with PAFF\n" );
- + h->param.i_bframe = 0;
- + }
- /* Detect default ffmpeg settings and terminate with an error. */
- if( b_open )
- @@ -937,8 +1001,19 @@ static int x264_validate_parameters( x264_t *h, int b_open )
- h->param.b_pic_struct = 1;
- }
- - h->param.i_frame_reference = x264_clip3( h->param.i_frame_reference, 1, X264_REF_MAX );
- - h->param.i_dpb_size = x264_clip3( h->param.i_dpb_size, 1, X264_REF_MAX );
- + if( PARAM_FIELD_ENCODE )
- + {
- + if( !(h->param.b_intra_refresh && h->param.i_frame_reference == 1) )
- + {
- + h->param.i_frame_reference <<= 1;
- + h->param.i_frame_reference = x264_clip3( h->param.i_frame_reference, 1, X264_REF_MAX );
- + }
- + }
- + else
- + {
- + h->param.i_frame_reference = x264_clip3( h->param.i_frame_reference, 1, X264_REF_MAX >> 1 );
- + h->param.i_dpb_size = x264_clip3( h->param.i_dpb_size, 1, X264_REF_MAX >> 1 );
- + }
- if( h->param.i_scenecut_threshold < 0 )
- h->param.i_scenecut_threshold = 0;
- h->param.analyse.i_direct_mv_pred = x264_clip3( h->param.analyse.i_direct_mv_pred, X264_DIRECT_PRED_NONE, X264_DIRECT_PRED_AUTO );
- @@ -947,7 +1022,19 @@ static int x264_validate_parameters( x264_t *h, int b_open )
- x264_log( h, X264_LOG_WARNING, "subme=0 + direct=temporal is not supported\n" );
- h->param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;
- }
- + if( PARAM_FIELD_ENCODE )
- + {
- + // FIXME: should this be part of the API for field encoding
- + if( 1 < h->param.i_keyint_max && h->param.i_keyint_max < X264_KEYINT_MAX_INFINITE )
- + h->param.i_keyint_max <<= 1;
- + h->param.i_keyint_max = x264_clip3( h->param.i_keyint_max, 1, X264_KEYINT_MAX_INFINITE );
- + if( 0 < h->param.i_bframe && h->param.i_bframe < X264_KEYINT_MAX_INFINITE )
- + h->param.i_bframe <<= 1;
- + }
- +
- h->param.i_bframe = x264_clip3( h->param.i_bframe, 0, X264_MIN( X264_BFRAME_MAX, h->param.i_keyint_max-1 ) );
- + if( PARAM_FIELD_ENCODE )
- + h->param.i_bframe &= ~1;
- h->param.i_bframe_bias = x264_clip3( h->param.i_bframe_bias, -90, 100 );
- if( h->param.i_bframe <= 1 )
- h->param.i_bframe_pyramid = X264_B_PYRAMID_NONE;
- @@ -978,10 +1065,16 @@ static int x264_validate_parameters( x264_t *h, int b_open )
- }
- if( !h->param.i_fps_num || !h->param.i_fps_den )
- {
- - h->param.i_fps_num = 25;
- + h->param.i_fps_num = 25*(1<<PARAM_FIELD_ENCODE);
- h->param.i_fps_den = 1;
- }
- float fps = (float) h->param.i_fps_num / h->param.i_fps_den;
- + if( PARAM_FIELD_ENCODE )
- + {
- + if( h->param.i_keyint_min != X264_KEYINT_MIN_AUTO )
- + if( 0 < h->param.i_keyint_min && h->param.i_keyint_min < X264_KEYINT_MAX_INFINITE )
- + h->param.i_keyint_min <<= 1;
- + }
- if( h->param.i_keyint_min == X264_KEYINT_MIN_AUTO )
- h->param.i_keyint_min = X264_MIN( h->param.i_keyint_max / 10, fps );
- h->param.i_keyint_min = x264_clip3( h->param.i_keyint_min, 1, h->param.i_keyint_max/2+1 );
- @@ -1138,9 +1231,9 @@ static int x264_validate_parameters( x264_t *h, int b_open )
- }
- }
- if( h->param.analyse.i_mv_range <= 0 )
- - h->param.analyse.i_mv_range = l->mv_range >> PARAM_INTERLACED;
- + h->param.analyse.i_mv_range = l->mv_range >> (PARAM_INTERLACED|PARAM_FIELD_ENCODE);
- else
- - h->param.analyse.i_mv_range = x264_clip3(h->param.analyse.i_mv_range, 32, 512 >> PARAM_INTERLACED);
- + h->param.analyse.i_mv_range = x264_clip3(h->param.analyse.i_mv_range, 32, 512 >> (PARAM_INTERLACED|PARAM_FIELD_ENCODE));
- }
- h->param.analyse.i_weighted_pred = x264_clip3( h->param.analyse.i_weighted_pred, X264_WEIGHTP_NONE, X264_WEIGHTP_SMART );
- @@ -1174,7 +1267,7 @@ static int x264_validate_parameters( x264_t *h, int b_open )
- }
- h->param.i_lookahead_threads = x264_clip3( h->param.i_lookahead_threads, 1, X264_MIN( max_sliced_threads, X264_LOOKAHEAD_THREAD_MAX ) );
- - if( PARAM_INTERLACED )
- + if( PARAM_INTERLACED || PARAM_FIELD_ENCODE )
- {
- if( h->param.analyse.i_me_method >= X264_ME_ESA )
- {
- @@ -1249,6 +1342,7 @@ static int x264_validate_parameters( x264_t *h, int b_open )
- BOOLIFY( b_deterministic );
- BOOLIFY( b_sliced_threads );
- BOOLIFY( b_interlaced );
- + BOOLIFY( b_field_encode );
- BOOLIFY( b_intra_refresh );
- BOOLIFY( b_aud );
- BOOLIFY( b_repeat_headers );
- @@ -1462,9 +1556,10 @@ x264_t *x264_encoder_open( x264_param_t *param )
- h->frames.i_delay += h->param.i_sync_lookahead;
- h->frames.i_delay += h->param.b_vfr_input;
- h->frames.i_bframe_delay = h->param.i_bframe ? (h->param.i_bframe_pyramid ? 2 : 1) : 0;
- + // FIXME what's the bframe delay for PAFF?
- h->frames.i_max_ref0 = h->param.i_frame_reference;
- - h->frames.i_max_ref1 = X264_MIN( h->sps->vui.i_num_reorder_frames, h->param.i_frame_reference );
- + h->frames.i_max_ref1 = X264_MIN( h->sps->vui.i_num_reorder_frames<<PARAM_FIELD_ENCODE, h->param.i_frame_reference );
- 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
- @@ -1504,7 +1599,7 @@ x264_t *x264_encoder_open( x264_param_t *param )
- x264_pixel_init( h->param.cpu, &h->pixf );
- x264_dct_init( h->param.cpu, &h->dctf );
- x264_zigzag_init( h->param.cpu, &h->zigzagf_progressive, &h->zigzagf_interlaced );
- - memcpy( &h->zigzagf, PARAM_INTERLACED ? &h->zigzagf_interlaced : &h->zigzagf_progressive, sizeof(h->zigzagf) );
- + memcpy( &h->zigzagf, PARAM_INTERLACED || PARAM_FIELD_ENCODE ? &h->zigzagf_interlaced : &h->zigzagf_progressive, sizeof(h->zigzagf) );
- x264_mc_init( h->param.cpu, &h->mc, h->param.b_cpu_independent );
- x264_quant_init( h, h->param.cpu, &h->quantf );
- x264_deblock_init( h->param.cpu, &h->loopf, PARAM_INTERLACED );
- @@ -1990,6 +2085,19 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
- return frame_size;
- }
- +static inline int x264_reference_distance( x264_t *h, x264_frame_t *frame )
- +{
- + if( h->param.i_frame_packing == 5 )
- + return (abs((h->fenc->i_frame^2) - (frame->i_frame^2))) +
- + ((h->fenc->i_frame&1) != (frame->i_frame&1));
- + else if( PARAM_FIELD_ENCODE )
- + {
- + return ((h->fenc->i_frame - frame->i_frame - 1) & ~1) + ((h->fenc->i_frame - frame->i_frame) && !!frame->i_frame);
- + }
- + else
- + return abs(h->fenc->i_frame - frame->i_frame);
- +}
- +
- /* Check to see whether we have chosen a reference list ordering different
- * from the standard's default. */
- static inline void x264_reference_check_reorder( x264_t *h )
- @@ -2003,17 +2111,49 @@ static inline void x264_reference_check_reorder( x264_t *h )
- return;
- }
- for( int list = 0; list <= (h->sh.i_type == SLICE_TYPE_B); list++ )
- - for( int i = 0; i < h->i_ref[list] - 1; i++ )
- + {
- + if( PARAM_FIELD_ENCODE )
- {
- - int framenum_diff = h->fref[list][i+1]->i_frame_num - h->fref[list][i]->i_frame_num;
- - int poc_diff = h->fref[list][i+1]->i_poc - h->fref[list][i]->i_poc;
- - /* P and B-frames use different default orders. */
- - if( h->sh.i_type == SLICE_TYPE_P ? framenum_diff > 0 : list == 1 ? poc_diff < 0 : poc_diff > 0 )
- + /* check the first field in the reference list has the same parity
- + * as the field to be encoded */
- + if( h->i_ref[list] > 0 && ((h->fenc->i_frame ^ h->fref[list][0]->i_frame) & 1))
- {
- + //printf("\n here %i \n", h->fenc->i_frame);
- h->b_ref_reorder[list] = 1;
- return;
- }
- +
- + /* FIXME: is there a cleaner way of doing this */
- + for( int i = 0; i < h->i_ref[list] - 1; i++ )
- + {
- + int dist = x264_reference_distance( h, h->fref[list][i] ) > x264_reference_distance( h, h->fref[list][i+1] );
- + int poc_diff = h->fref[list][i+1]->i_poc - h->fref[list][i]->i_poc;
- + //printf("\n %i %i %i %i %i \n", h->fenc->i_frame, i, dist, h->fref[list][i]->i_frame, h->fref[list][i+1]->i_frame );
- + /* P and B-frames use different default orders. */
- + // FIXME b-frames
- + if( h->sh.i_type == SLICE_TYPE_P ? dist : list == 1 ? poc_diff < 0 : poc_diff > 0 )
- + {
- + h->b_ref_reorder[list] = 1;
- + return;
- + }
- + }
- +
- + }
- + else
- + {
- + for( int i = 0; i < h->i_ref[list] - 1; i++ )
- + {
- + int picnum_diff = x264_diff_pic_num( h, h->fref[list][i+1], h->fref[list][i] );
- + int poc_diff = h->fref[list][i+1]->i_poc - h->fref[list][i]->i_poc;
- + /* P and B-frames use different default orders. */
- + if( h->sh.i_type == SLICE_TYPE_P ? picnum_diff > 0 : list == 1 ? poc_diff < 0 : poc_diff > 0 )
- + {
- + h->b_ref_reorder[list] = 1;
- + return;
- + }
- + }
- }
- + }
- }
- /* return -1 on failure, else return the index of the new reference frame */
- @@ -2140,15 +2280,6 @@ static void x264_weighted_pred_init( x264_t *h )
- h->sh.weight[0][2].i_denom = h->sh.weight[0][1].i_denom;
- }
- -static inline int x264_reference_distance( x264_t *h, x264_frame_t *frame )
- -{
- - if( h->param.i_frame_packing == 5 )
- - return abs((h->fenc->i_frame&~1) - (frame->i_frame&~1)) +
- - ((h->fenc->i_frame&1) != (frame->i_frame&1));
- - else
- - return abs(h->fenc->i_frame - frame->i_frame);
- -}
- -
- static inline void x264_reference_build_list( x264_t *h, int i_poc )
- {
- int b_ok;
- @@ -2188,13 +2319,13 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
- for( int i = h->i_ref[0]-1; i >= h->i_ref[0] - h->sh.i_mmco_remove_from_end; i-- )
- {
- - int diff = h->i_frame_num - h->fref[0][i]->i_frame_num;
- + int diff = x264_diff_pic_num( h, h->fdec, h->fref[0][i] );
- h->sh.mmco[h->sh.i_mmco_command_count].i_poc = h->fref[0][i]->i_poc;
- h->sh.mmco[h->sh.i_mmco_command_count++].i_difference_of_pic_nums = diff;
- }
- }
- - /* Order reference lists by distance from the current frame. */
- + /* Order reference lists by distance from the current picture. */
- for( int list = 0; list < 2; list++ )
- {
- h->fref_nearest[list] = h->fref[list][0];
- @@ -2206,6 +2337,12 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
- if( list ? h->fref[list][i+1]->i_poc < h->fref_nearest[list]->i_poc
- : h->fref[list][i+1]->i_poc > h->fref_nearest[list]->i_poc )
- h->fref_nearest[list] = h->fref[list][i+1];
- +
- + printf("\n frame %i refi %i refi+1 %i dist %i %i", h->fenc->i_frame, h->fref[list][i]->i_frame,
- + h->fref[list][i+1]->i_frame, x264_reference_distance( h, h->fref[list][i] ),
- + x264_reference_distance( h, h->fref[list][i+1] ) );
- +
- +
- if( x264_reference_distance( h, h->fref[list][i] ) > x264_reference_distance( h, h->fref[list][i+1] ) )
- {
- XCHG( x264_frame_t*, h->fref[list][i], h->fref[list][i+1] );
- @@ -2224,7 +2361,7 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
- /* For Blu-ray compliance, don't reference frames outside of the minigop. */
- if( IS_X264_TYPE_B( h->fenc->i_type ) && h->param.b_bluray_compat )
- - h->i_ref[0] = X264_MIN( h->i_ref[0], IS_X264_TYPE_B( h->fref[0][0]->i_type ) + 1 );
- + h->i_ref[0] = X264_MIN( h->i_ref[0], (IS_X264_TYPE_B( h->fref[0][0]->i_type ) + 1)<<PARAM_FIELD_ENCODE );
- /* add duplicates */
- if( h->fenc->i_type == X264_TYPE_P )
- @@ -2409,8 +2546,13 @@ static inline int x264_reference_update( x264_t *h )
- /* move frame in the buffer */
- x264_frame_push( h->frames.reference, h->fdec );
- - if( h->frames.reference[h->sps->i_num_ref_frames] )
- + if( h->frames.reference[h->sps->i_num_ref_frames<<PARAM_FIELD_ENCODE] )
- + {
- x264_frame_push_unused( h, x264_frame_shift( h->frames.reference ) );
- + if( PARAM_FIELD_ENCODE )
- + x264_frame_push_unused( h, x264_frame_shift( h->frames.reference ) ); /* 2nd field */
- + }
- +
- h->fdec = x264_frame_pop_unused( h, 1 );
- if( !h->fdec )
- return -1;
- @@ -2432,8 +2574,8 @@ static inline void x264_reference_hierarchy_reset( x264_t *h )
- /* look for delay frames -- chain must only contain frames that are disposable */
- for( int i = 0; h->frames.current[i] && IS_DISPOSABLE( h->frames.current[i]->i_type ); i++ )
- - b_hasdelayframe |= h->frames.current[i]->i_coded
- - != h->frames.current[i]->i_frame + h->sps->vui.i_num_reorder_frames;
- + b_hasdelayframe |= (h->frames.current[i]->i_coded>>PARAM_FIELD_ENCODE)
- + != (h->frames.current[i]->i_frame>>PARAM_FIELD_ENCODE) + h->sps->vui.i_num_reorder_frames;
- /* This function must handle b-pyramid and clear frames for open-gop */
- if( h->param.i_bframe_pyramid != X264_B_PYRAMID_STRICT && !b_hasdelayframe && h->frames.i_poc_last_open_gop == -1 )
- @@ -2448,7 +2590,7 @@ static inline void x264_reference_hierarchy_reset( x264_t *h )
- || ( h->frames.reference[ref]->i_poc < h->frames.i_poc_last_open_gop
- && h->sh.i_type != SLICE_TYPE_B ) )
- {
- - int diff = h->i_frame_num - h->frames.reference[ref]->i_frame_num;
- + int diff = x264_diff_pic_num( h, h->fdec, h->frames.reference[ref] );
- h->sh.mmco[h->sh.i_mmco_command_count].i_difference_of_pic_nums = diff;
- h->sh.mmco[h->sh.i_mmco_command_count++].i_poc = h->frames.reference[ref]->i_poc;
- x264_frame_push_unused( h, x264_frame_shift( &h->frames.reference[ref] ) );
- @@ -2459,7 +2601,7 @@ static inline void x264_reference_hierarchy_reset( x264_t *h )
- /* Prepare room in the dpb for the delayed display time of the later b-frame's */
- if( h->param.i_bframe_pyramid )
- - h->sh.i_mmco_remove_from_end = X264_MAX( ref + 2 - h->frames.i_max_dpb, 0 );
- + h->sh.i_mmco_remove_from_end = X264_MAX( (ref>>PARAM_FIELD_ENCODE) + 2 - h->frames.i_max_dpb, 0 ) << PARAM_FIELD_ENCODE;
- }
- static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
- @@ -2508,8 +2650,6 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
- h->sh_backup = h->sh;
- }
- - h->fdec->i_frame_num = h->sh.i_frame_num;
- -
- if( h->sps->i_poc_type == 0 )
- {
- h->sh.i_poc = h->fdec->i_poc;
- @@ -3174,6 +3314,7 @@ int x264_encoder_invalidate_reference( x264_t *h, int64_t pts )
- * P 4 2*6
- * B 5 2*4
- * B 6 2*5
- + *
- ****************************************************************************/
- int x264_encoder_encode( x264_t *h,
- x264_nal_t **pp_nal, int *pi_nal,
- @@ -3245,13 +3386,16 @@ int x264_encoder_encode( x264_t *h,
- {
- #if HAVE_INTERLACED
- int b_interlaced = fenc->param ? fenc->param->b_interlaced : h->param.b_interlaced;
- + int b_field_encode = fenc->param ? fenc->param->b_field_encode : h->param.b_field_encode;
- #else
- int b_interlaced = 0;
- + int b_field_encode = 0;
- #endif
- - if( b_interlaced )
- + if( b_interlaced || b_field_encode )
- {
- int b_tff = fenc->param ? fenc->param->b_tff : h->param.b_tff;
- - fenc->i_pic_struct = b_tff ? PIC_STRUCT_TOP_BOTTOM : PIC_STRUCT_BOTTOM_TOP;
- + fenc->i_pic_struct = b_interlaced ? b_tff ? PIC_STRUCT_TOP_BOTTOM : PIC_STRUCT_BOTTOM_TOP
- + : (fenc->i_frame ^ !b_tff) & 1 ? PIC_STRUCT_BOTTOM : PIC_STRUCT_TOP;
- }
- else
- fenc->i_pic_struct = PIC_STRUCT_PROGRESSIVE;
- @@ -3357,7 +3501,9 @@ int x264_encoder_encode( x264_t *h,
- h->b_ref_reorder[0] =
- h->b_ref_reorder[1] = 0;
- h->fdec->i_poc =
- - h->fenc->i_poc = 2 * ( h->fenc->i_frame - X264_MAX( h->frames.i_last_idr, 0 ) );
- + h->fenc->i_poc = (2-PARAM_FIELD_ENCODE) * ( h->fenc->i_frame - X264_MAX( h->frames.i_last_idr, 0 ) );
- + h->fdec->i_frame = h->fenc->i_frame;
- + h->fdec->i_frame_num = h->i_frame_num;
- /* ------------------- Setup frame context ----------------------------- */
- /* 5: Init data dependent of frame type */
- @@ -3384,15 +3530,19 @@ int x264_encoder_encode( x264_t *h,
- i_nal_type = NAL_SLICE;
- i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
- h->sh.i_type = SLICE_TYPE_P;
- - x264_reference_hierarchy_reset( h );
- - h->frames.i_poc_last_open_gop = -1;
- + if( !(h->fenc->i_coded & PARAM_FIELD_ENCODE) ) // 1st field
- + {
- + x264_reference_hierarchy_reset( h );
- + h->frames.i_poc_last_open_gop = -1;
- + }
- }
- else if( h->fenc->i_type == X264_TYPE_BREF )
- {
- i_nal_type = NAL_SLICE;
- i_nal_ref_idc = h->param.i_bframe_pyramid == X264_B_PYRAMID_STRICT ? NAL_PRIORITY_LOW : NAL_PRIORITY_HIGH;
- h->sh.i_type = SLICE_TYPE_B;
- - x264_reference_hierarchy_reset( h );
- + if( !PARAM_FIELD_ENCODE || !(h->fenc->i_coded & 1) ) // 1st field
- + x264_reference_hierarchy_reset( h );
- }
- else /* B frame */
- {
- @@ -3402,7 +3552,6 @@ int x264_encoder_encode( x264_t *h,
- }
- h->fdec->i_type = h->fenc->i_type;
- - h->fdec->i_frame = h->fenc->i_frame;
- h->fenc->b_kept_as_ref =
- h->fdec->b_kept_as_ref = i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE && h->param.i_keyint_max > 1;
- @@ -3692,7 +3841,11 @@ int x264_encoder_encode( x264_t *h,
- x264_weighted_pred_init( h );
- if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE )
- - h->i_frame_num++;
- + {
- + int second_field = h->fenc->i_frame & 1;
- + if( !PARAM_FIELD_ENCODE || second_field )
- + h->i_frame_num++;
- + }
- /* Write frame */
- h->i_threadslice_start = 0;
- diff --git a/encoder/lookahead.c b/encoder/lookahead.c
- index a6e861b..97a7b67 100644
- --- a/encoder/lookahead.c
- +++ b/encoder/lookahead.c
- @@ -58,8 +58,13 @@ static void x264_lookahead_shift( x264_sync_frame_list_t *dst, x264_sync_frame_l
- static void x264_lookahead_update_last_nonb( x264_t *h, x264_frame_t *new_nonb )
- {
- - if( h->lookahead->last_nonb )
- + if( PARAM_FIELD_ENCODE && h->lookahead->penultimate_nonb )
- + x264_frame_push_unused( h, h->lookahead->penultimate_nonb );
- +
- + if( !PARAM_FIELD_ENCODE && h->lookahead->last_nonb )
- x264_frame_push_unused( h, h->lookahead->last_nonb );
- + if( PARAM_FIELD_ENCODE )
- + h->lookahead->penultimate_nonb = h->lookahead->last_nonb;
- h->lookahead->last_nonb = new_nonb;
- new_nonb->i_reference_count++;
- }
- @@ -67,10 +72,12 @@ static void x264_lookahead_update_last_nonb( x264_t *h, x264_frame_t *new_nonb )
- #if HAVE_THREAD
- static void x264_lookahead_slicetype_decide( x264_t *h )
- {
- + //printf("\n next %i \n", h->lookahead->next.list[0]->i_frame );
- +
- x264_stack_align( x264_slicetype_decide, h );
- x264_lookahead_update_last_nonb( h, h->lookahead->next.list[0] );
- - int shift_frames = h->lookahead->next.list[0]->i_bframes + 1;
- + int shift_frames = h->lookahead->last_nonb->i_bframes + 1;
- x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex );
- while( h->lookahead->ofbuf.i_size == h->lookahead->ofbuf.i_max_size )
- @@ -80,6 +87,7 @@ static void x264_lookahead_slicetype_decide( x264_t *h )
- x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, shift_frames );
- x264_pthread_mutex_unlock( &h->lookahead->next.mutex );
- + // FIXME this probably will be broken
- /* For MB-tree and VBV lookahead, we have to perform propagation analysis on I-frames too. */
- if( h->lookahead->b_analyse_keyframe && IS_X264_TYPE_I( h->lookahead->last_nonb->i_type ) )
- x264_stack_align( x264_slicetype_analyse, h, shift_frames );
- @@ -179,6 +187,8 @@ void x264_lookahead_delete( x264_t *h )
- x264_sync_frame_list_delete( &h->lookahead->next );
- if( h->lookahead->last_nonb )
- x264_frame_push_unused( h, h->lookahead->last_nonb );
- + if( h->lookahead->penultimate_nonb )
- + x264_frame_push_unused( h, h->lookahead->penultimate_nonb );
- x264_sync_frame_list_delete( &h->lookahead->ofbuf );
- x264_free( h->lookahead );
- }
- @@ -232,7 +242,7 @@ void x264_lookahead_get_frames( x264_t *h )
- x264_stack_align( x264_slicetype_decide, h );
- x264_lookahead_update_last_nonb( h, h->lookahead->next.list[0] );
- - int shift_frames = h->lookahead->next.list[0]->i_bframes + 1;
- + int shift_frames = h->lookahead->last_nonb->i_bframes + 1;
- x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, shift_frames );
- /* For MB-tree and VBV lookahead, we have to perform propagation analysis on I-frames too. */
- diff --git a/encoder/macroblock.c b/encoder/macroblock.c
- index 351650a..da53c0e 100644
- --- a/encoder/macroblock.c
- +++ b/encoder/macroblock.c
- @@ -649,6 +649,8 @@ static ALWAYS_INLINE void x264_macroblock_encode_internal( x264_t *h, int plane_
- if( chroma )
- {
- int v_shift = CHROMA_V_SHIFT;
- + if( v_shift && PARAM_FIELD_ENCODE )
- + mvy += h->mb.i_mvy_offset[0][0];
- int height = 16 >> v_shift;
- /* Special case for mv0, which is (of course) very common in P-skip mode. */
- @@ -1016,6 +1018,10 @@ static ALWAYS_INLINE int x264_macroblock_probe_skip_internal( x264_t *h, int b_b
- if( !b_bidir )
- {
- + int v_shift = CHROMA_V_SHIFT;
- + if( v_shift && PARAM_FIELD_ENCODE )
- + mvp[1] += h->mb.i_mvy_offset[0][0];
- +
- /* Special case for mv0, which is (of course) very common in P-skip mode. */
- if( M32( mvp ) )
- h->mc.mc_chroma( h->mb.pic.p_fdec[1], h->mb.pic.p_fdec[2], FDEC_STRIDE,
- diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
- index f71eb5f..161295e 100644
- --- a/encoder/ratecontrol.c
- +++ b/encoder/ratecontrol.c
- @@ -749,7 +749,7 @@ int x264_ratecontrol_new( x264_t *h )
- if( h->param.i_fps_num > 0 && h->param.i_fps_den > 0 )
- rc->fps = (float) h->param.i_fps_num / h->param.i_fps_den;
- else
- - rc->fps = 25.0;
- + rc->fps = 25.0*(1+PARAM_FIELD_ENCODE);
- if( h->param.rc.b_mb_tree )
- {
- diff --git a/encoder/set.c b/encoder/set.c
- index 1a40b71..652295e 100644
- --- a/encoder/set.c
- +++ b/encoder/set.c
- @@ -144,7 +144,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- /* extra slot with pyramid so that we don't have to override the
- * order of forgetting old pictures */
- sps->vui.i_max_dec_frame_buffering =
- - sps->i_num_ref_frames = X264_MIN(X264_REF_MAX, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames,
- + sps->i_num_ref_frames = X264_MIN(X264_REF_MAX >> 1, X264_MAX4(param->i_frame_reference>>param->b_field_encode, 1 + sps->vui.i_num_reorder_frames,
- param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size));
- sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT;
- if( param->i_keyint_max == 1 )
- @@ -166,7 +166,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- while( (1 << sps->i_log2_max_frame_num) <= max_frame_num )
- sps->i_log2_max_frame_num++;
- - sps->i_poc_type = param->i_bframe || param->b_interlaced ? 0 : 2;
- + sps->i_poc_type = param->i_bframe || param->b_interlaced || param->b_field_encode ? 0 : 2;
- if( sps->i_poc_type == 0 )
- {
- int max_delta_poc = (param->i_bframe + 2) * (!!param->i_bframe_pyramid + 1) * 2;
- @@ -178,8 +178,9 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- sps->b_vui = 1;
- sps->b_gaps_in_frame_num_value_allowed = 0;
- - sps->b_frame_mbs_only = !(param->b_interlaced || param->b_fake_interlaced);
- - if( !sps->b_frame_mbs_only )
- + sps->b_frame_mbs_only = !(param->b_interlaced || param->b_fake_interlaced || param->b_field_encode);
- + sps->b_half_height = param->b_interlaced || param->b_fake_interlaced;
- + if( sps->b_half_height )
- sps->i_mb_height = ( sps->i_mb_height + 1 ) & ~1;
- sps->b_mb_adaptive_frame_field = param->b_interlaced;
- sps->b_direct8x8_inference = 1;
- @@ -187,7 +188,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- sps->crop.i_left = param->crop_rect.i_left;
- sps->crop.i_top = param->crop_rect.i_top;
- sps->crop.i_right = param->crop_rect.i_right + sps->i_mb_width*16 - param->i_width;
- - sps->crop.i_bottom = (param->crop_rect.i_bottom + sps->i_mb_height*16 - param->i_height) >> !sps->b_frame_mbs_only;
- + sps->crop.i_bottom = (param->crop_rect.i_bottom + sps->i_mb_height*16 - param->i_height) >> sps->b_half_height;
- sps->b_crop = sps->crop.i_left || sps->crop.i_top ||
- sps->crop.i_right || sps->crop.i_bottom;
- @@ -241,7 +242,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- if( sps->vui.b_timing_info_present )
- {
- sps->vui.i_num_units_in_tick = param->i_timebase_num;
- - sps->vui.i_time_scale = param->i_timebase_den * 2;
- + sps->vui.i_time_scale = param->i_timebase_den * (2-param->b_field_encode);
- sps->vui.b_fixed_frame_rate = !param->b_vfr_input;
- }
- @@ -295,7 +296,7 @@ void x264_sps_write( bs_t *s, x264_sps_t *sps )
- bs_write_ue( s, sps->i_num_ref_frames );
- bs_write1( s, sps->b_gaps_in_frame_num_value_allowed );
- bs_write_ue( s, sps->i_mb_width - 1 );
- - bs_write_ue( s, (sps->i_mb_height >> !sps->b_frame_mbs_only) - 1);
- + bs_write_ue( s, (sps->i_mb_height >> sps->b_half_height) - 1);
- bs_write1( s, sps->b_frame_mbs_only );
- if( !sps->b_frame_mbs_only )
- bs_write1( s, sps->b_mb_adaptive_frame_field );
- @@ -819,8 +820,7 @@ int x264_validate_levels( x264_t *h, int verbose )
- l++;
- if( l->frame_size < mbs
- - || l->frame_size*8 < h->sps->i_mb_width * h->sps->i_mb_width
- - || l->frame_size*8 < h->sps->i_mb_height * h->sps->i_mb_height )
- + || l->frame_size*8 < h->sps->i_mb_width * h->sps->i_mb_width )
- ERROR( "frame MB size (%dx%d) > level limit (%d)\n",
- h->sps->i_mb_width, h->sps->i_mb_height, l->frame_size );
- if( dpb > l->dpb )
- @@ -836,6 +836,7 @@ int x264_validate_levels( x264_t *h, int verbose )
- CHECK( "MV range", l->mv_range, h->param.analyse.i_mv_range );
- CHECK( "interlaced", !l->frame_only, h->param.b_interlaced );
- CHECK( "fake interlaced", !l->frame_only, h->param.b_fake_interlaced );
- + CHECK( "field encoding", !l->frame_only, h->param.b_field_encode );
- if( h->param.i_fps_den > 0 )
- CHECK( "MB rate", l->mbps, (int64_t)mbs * h->param.i_fps_num / h->param.i_fps_den );
- diff --git a/encoder/slicetype.c b/encoder/slicetype.c
- index 0f4d831..d64c89c 100644
- --- a/encoder/slicetype.c
- +++ b/encoder/slicetype.c
- @@ -859,6 +859,9 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
- }
- if( do_search[1] ) fenc->lowres_mvs[1][p1-b-1][0][0] = 0;
- + if( b != p0 )
- + printf("\n do search %i %i %i \n", do_search[0], do_search[1], fenc->lowres_mvs[0][b-p0-1][0][0] );
- +
- if( p1 != p0 )
- dist_scale_factor = ( ((b-p0) << 8) + ((p1-p0) >> 1) ) / (p1-p0);
- @@ -1101,6 +1104,8 @@ static void x264_macroblock_tree( x264_t *h, x264_mb_analysis_t *a, x264_frame_t
- int i = num_frames;
- + printf("\n MBTREE num_frames %i \n", num_frames );
- +
- if( b_intra )
- x264_slicetype_frame_cost( h, a, frames, 0, 0, 0, 0 );
- @@ -1501,6 +1506,9 @@ void x264_slicetype_analyse( x264_t *h, int intra_minigop )
- return;
- }
- + if( PARAM_FIELD_ENCODE && frames[0]->i_frame ^ 1 )
- + frames[1]->i_type = X264_TYPE_P;
- +
- #if HAVE_OPENCL
- x264_opencl_slicetype_prep( h, frames, num_frames, a.i_lambda );
- #endif
- @@ -1640,7 +1648,7 @@ void x264_slicetype_analyse( x264_t *h, int intra_minigop )
- void x264_slicetype_decide( x264_t *h )
- {
- - x264_frame_t *frames[X264_BFRAME_MAX+2];
- + x264_frame_t *frames[X264_BFRAME_MAX+3];
- x264_frame_t *frm;
- int bframes;
- int brefs;
- @@ -1655,7 +1663,8 @@ void x264_slicetype_decide( x264_t *h )
- if( h->param.b_vfr_input )
- {
- if( lookahead_size-- > 1 )
- - h->lookahead->next.list[i]->i_duration = 2 * (h->lookahead->next.list[i+1]->i_pts - h->lookahead->next.list[i]->i_pts);
- + h->lookahead->next.list[i]->i_duration = (2-PARAM_FIELD_ENCODE)
- + * (h->lookahead->next.list[i+1]->i_pts - h->lookahead->next.list[i]->i_pts);
- else
- h->lookahead->next.list[i]->i_duration = h->i_prev_duration;
- }
- @@ -1695,6 +1704,14 @@ void x264_slicetype_decide( x264_t *h )
- for( bframes = 0, brefs = 0;; bframes++ )
- {
- frm = h->lookahead->next.list[bframes];
- +
- + /* Any non-scenecut field following an I-field must be a P-field */
- + if( PARAM_FIELD_ENCODE && !IS_X264_TYPE_I( frm->i_type ) && frm->i_frame == h->lookahead->i_last_keyframe+1 )
- + {
- + frm->i_type = X264_TYPE_P;
- + frm->b_ref_opp_field = 1;
- + }
- +
- if( frm->i_type == X264_TYPE_BREF && h->param.i_bframe_pyramid < X264_B_PYRAMID_NORMAL &&
- brefs == h->param.i_bframe_pyramid )
- {
- @@ -1705,7 +1722,7 @@ void x264_slicetype_decide( x264_t *h )
- /* pyramid with multiple B-refs needs a big enough dpb that the preceding P-frame stays available.
- smaller dpb could be supported by smart enough use of mmco, but it's easier just to forbid it. */
- else if( frm->i_type == X264_TYPE_BREF && h->param.i_bframe_pyramid == X264_B_PYRAMID_NORMAL &&
- - brefs && h->param.i_frame_reference <= (brefs+3) )
- + brefs && (h->param.i_frame_reference>>PARAM_FIELD_ENCODE) <= (brefs+3) )
- {
- frm->i_type = X264_TYPE_B;
- x264_log( h, X264_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid %s and %d reference frames\n",
- @@ -1748,16 +1765,18 @@ void x264_slicetype_decide( x264_t *h )
- frm->b_keyframe = 1;
- if( bframes > 0 )
- {
- - bframes--;
- + bframes -= 1+PARAM_FIELD_ENCODE;
- h->lookahead->next.list[bframes]->i_type = X264_TYPE_P;
- + if( PARAM_FIELD_ENCODE )
- + h->lookahead->next.list[bframes+1]->i_type = X264_TYPE_P;
- }
- }
- if( bframes == h->param.i_bframe ||
- - !h->lookahead->next.list[bframes+1] )
- + !h->lookahead->next.list[bframes+1+PARAM_FIELD_ENCODE] )
- {
- if( IS_X264_TYPE_B( frm->i_type ) )
- - x264_log( h, X264_LOG_WARNING, "specified frame type is not compatible with max B-frames\n" );
- + x264_log( h, X264_LOG_WARNING, "specified frame type is not compatible with max B-frames, frame %i\n", frm->i_frame );
- if( frm->i_type == X264_TYPE_AUTO
- || IS_X264_TYPE_B( frm->i_type ) )
- frm->i_type = X264_TYPE_P;
- @@ -1774,7 +1793,15 @@ void x264_slicetype_decide( x264_t *h )
- if( bframes )
- h->lookahead->next.list[bframes-1]->b_last_minigop_bframe = 1;
- - h->lookahead->next.list[bframes]->i_bframes = bframes;
- +
- + if( PARAM_FIELD_ENCODE )
- + {
- + h->lookahead->next.list[bframes+0]->i_bframes = 0;
- + if( lookahead_size > 1 )
- + h->lookahead->next.list[bframes+1]->i_bframes = bframes;
- + }
- + else
- + h->lookahead->next.list[bframes]->i_bframes = bframes;
- /* insert a bref into the sequence */
- if( h->param.i_bframe_pyramid && bframes > 1 && !brefs )
- @@ -1792,12 +1819,30 @@ void x264_slicetype_decide( x264_t *h )
- x264_lowres_context_init( h, &a );
- - frames[0] = h->lookahead->last_nonb;
- - memcpy( &frames[1], h->lookahead->next.list, (bframes+1) * sizeof(x264_frame_t*) );
- - if( IS_X264_TYPE_I( h->lookahead->next.list[bframes]->i_type ) )
- - p0 = bframes + 1;
- - else // P
- - p0 = 0;
- + if( PARAM_FIELD_ENCODE )
- + {
- + frames[0] = h->lookahead->penultimate_nonb;
- + frames[1] = h->lookahead->last_nonb;
- + memcpy( &frames[2], h->lookahead->next.list, (bframes+1) * sizeof(x264_frame_t*) );
- + p1 = b = 2;
- + if( frames[1] && IS_X264_TYPE_I( frames[1]->i_type ) )
- + p0 = 1;
- + else if( IS_X264_TYPE_I( h->lookahead->next.list[bframes]->i_type ) )
- + p0 = bframes + 2;
- + else // P
- + p0 = 0;
- + }
- + else
- + {
- + frames[0] = h->lookahead->last_nonb;
- + memcpy( &frames[1], h->lookahead->next.list, (bframes+1) * sizeof(x264_frame_t*) );
- + if( IS_X264_TYPE_I( h->lookahead->next.list[bframes]->i_type ) )
- + p0 = bframes + 1;
- + else // P
- + p0 = 0;
- + }
- +
- + printf("\n SD %i %i %i \n", p0, p1, b );
- x264_slicetype_frame_cost( h, &a, frames, p0, p1, b, 0 );
- @@ -1835,7 +1880,7 @@ void x264_slicetype_decide( x264_t *h )
- int i_coded = h->lookahead->next.list[0]->i_frame;
- if( bframes )
- {
- - int idx_list[] = { brefs+1, 1 };
- + int idx_list[2] = { brefs+1+PARAM_FIELD_ENCODE, 1+PARAM_FIELD_ENCODE };
- for( int i = 0; i < bframes; i++ )
- {
- int idx = idx_list[h->lookahead->next.list[i]->i_type == X264_TYPE_BREF]++;
- @@ -1844,6 +1889,11 @@ void x264_slicetype_decide( x264_t *h )
- }
- frames[0] = h->lookahead->next.list[bframes];
- frames[0]->i_reordered_pts = h->lookahead->next.list[0]->i_pts;
- + if( PARAM_FIELD_ENCODE )
- + {
- + frames[1] = h->lookahead->next.list[bframes+1];
- + frames[1]->i_reordered_pts = h->lookahead->next.list[1]->i_pts;
- + }
- memcpy( h->lookahead->next.list, frames, (bframes+1) * sizeof(x264_frame_t*) );
- }
- @@ -1868,22 +1918,34 @@ int x264_rc_analyse_slice( x264_t *h )
- {
- int p0 = 0, p1, b;
- int cost;
- + x264_frame_t **frames;
- x264_emms();
- if( IS_X264_TYPE_I(h->fenc->i_type) )
- p1 = b = 0;
- else if( h->fenc->i_type == X264_TYPE_P )
- - p1 = b = h->fenc->i_bframes + 1;
- + {
- + p1 = b = h->fenc->i_bframes + 1+PARAM_FIELD_ENCODE;
- + if( PARAM_FIELD_ENCODE && h->fenc->b_ref_opp_field )
- + {
- + p1--;
- + b--;
- + }
- + frames = &h->fenc - b;
- + }
- else //B
- {
- p1 = (h->fref_nearest[1]->i_poc - h->fref_nearest[0]->i_poc)/2;
- b = (h->fenc->i_poc - h->fref_nearest[0]->i_poc)/2;
- }
- /* We don't need to assign p0/p1 since we are not performing any real analysis here. */
- - x264_frame_t **frames = &h->fenc - b;
- + frames = &h->fenc - b;
- +
- + printf("\n num %i ref %i p1 %i b %i \n", frames[p1]->i_frame, h->fenc->b_ref_opp_field, p1, b );
- /* cost should have been already calculated by x264_slicetype_decide */
- cost = frames[b]->i_cost_est[b-p0][p1-b];
- + printf("\n b-p0 %i p1-b %i \n", b-p0, p1-b );
- assert( cost >= 0 );
- if( h->param.rc.b_mb_tree && !h->param.rc.b_stat_read )
- diff --git a/x264.c b/x264.c
- index 427d06c..7599331 100644
- --- a/x264.c
- +++ b/x264.c
- @@ -691,6 +691,7 @@ static void help( x264_param_t *defaults, int longhelp )
- H2( " --slice-min-mbs <integer> Limit the size of each slice in macroblocks (min)\n");
- H0( " --tff Enable interlaced mode (top field first)\n" );
- H0( " --bff Enable interlaced mode (bottom field first)\n" );
- + H0( " --field-encode Enable field encoding - one frame will be encoded as two fields \n" );
- H2( " --constrained-intra Enable constrained intra prediction.\n" );
- H0( " --pulldown <string> Use soft pulldown to change frame rate\n"
- " - none, 22, 32, 64, double, triple, euro (requires cfr input)\n" );
- @@ -999,6 +1000,7 @@ static struct option long_options[] =
- { "tff", no_argument, NULL, OPT_INTERLACED },
- { "bff", no_argument, NULL, OPT_INTERLACED },
- { "no-interlaced", no_argument, NULL, OPT_INTERLACED },
- + { "field-encode", no_argument, NULL, OPT_INTERLACED },
- { "constrained-intra", no_argument, NULL, 0 },
- { "cabac", no_argument, NULL, 0 },
- { "no-cabac", no_argument, NULL, 0 },
- @@ -1857,9 +1859,17 @@ static int encode( x264_param_t *param, cli_opt_t *opt )
- opt->b_progress &= param->i_log_level < X264_LOG_DEBUG;
- + if( param->b_field_encode )
- + {
- + FAIL_IF_ERROR2( param->b_vfr_input, "field encoding is not compatible with vfr\n" );
- + param->i_fps_num <<= 1;
- + param->i_height >>= 1;
- + }
- +
- /* set up pulldown */
- - if( opt->i_pulldown && !param->b_vfr_input )
- + if( opt->i_pulldown )
- {
- + FAIL_IF_ERROR2( param->b_field_encode, "field encoding is not compatible with pulldown\n" );
- param->b_pulldown = 1;
- param->b_pic_struct = 1;
- pulldown = &pulldown_values[opt->i_pulldown];
- @@ -1936,18 +1946,43 @@ static int encode( x264_param_t *param, cli_opt_t *opt )
- parse_qpfile( opt, &pic, i_frame + opt->i_seek );
- prev_dts = last_dts;
- - i_frame_size = encode_frame( h, opt->hout, &pic, &last_dts );
- - if( i_frame_size < 0 )
- +
- + if( param->b_field_encode )
- {
- - b_ctrl_c = 1; /* lie to exit the loop */
- - retval = -1;
- + for( int i = 0; i < pic.img.i_plane; i++ )
- + {
- + pic.img.plane[i] += param->b_tff ? 0 : pic.img.i_stride[i]; /* first field */
- + pic.img.i_stride[i] <<= 1;
- + }
- }
- - else if( i_frame_size )
- +
- + for( int i = 0; i < 1+param->b_field_encode; i++ )
- {
- - i_file += i_frame_size;
- - i_frame_output++;
- - if( i_frame_output == 1 )
- - first_dts = prev_dts = last_dts;
- + /* x264cli takes in frames but in field mode libx264 takes fields
- + * the encode loop separates the fields from the frame */
- + if( i )
- + {
- + for( int j = 0; j < pic.img.i_plane; j++ )
- + pic.img.plane[j] += param->b_tff ? (pic.img.i_stride[j] >> 1) : -(pic.img.i_stride[j] >> 1); /* second field */
- + pic.i_pts++;
- + }
- + else
- + pic.i_pts <<= 1;
- +
- + i_frame_size = encode_frame( h, opt->hout, &pic, &last_dts );
- + if( i_frame_size < 0 )
- + {
- + b_ctrl_c = 1; /* lie to exit the outer encode loop */
- + retval = -1;
- + break;
- + }
- + else if( i_frame_size )
- + {
- + i_file += i_frame_size;
- + i_frame_output++;
- + if( i_frame_output == 1 )
- + first_dts = prev_dts = last_dts;
- + }
- }
- if( filter.release_frame( opt->hin, &cli_pic, i_frame + opt->i_seek ) )
- @@ -1955,7 +1990,8 @@ static int encode( x264_param_t *param, cli_opt_t *opt )
- /* update status line (up to 1000 times per input file) */
- if( opt->b_progress && i_frame_output )
- - i_previous = print_status( i_start, i_previous, i_frame_output, param->i_frame_total, i_file, param, 2 * last_dts - prev_dts - first_dts );
- + i_previous = print_status( i_start, i_previous, i_frame_output, param->i_frame_total*(1+param->b_field_encode),
- + i_file, param, 2 * last_dts - prev_dts - first_dts );
- }
- /* Flush delayed frames */
- while( !b_ctrl_c && x264_encoder_delayed_frames( h ) )
- @@ -1975,7 +2011,8 @@ static int encode( x264_param_t *param, cli_opt_t *opt )
- first_dts = prev_dts = last_dts;
- }
- if( opt->b_progress && i_frame_output )
- - i_previous = print_status( i_start, i_previous, i_frame_output, param->i_frame_total, i_file, param, 2 * last_dts - prev_dts - first_dts );
- + i_previous = print_status( i_start, i_previous, i_frame_output, param->i_frame_total*(1+param->b_field_encode),
- + i_file, param, 2 * last_dts - prev_dts - first_dts );
- }
- fail:
- if( pts_warning_cnt >= MAX_PTS_WARNING && cli_log_level < X264_LOG_DEBUG )
- @@ -1989,6 +2026,10 @@ fail:
- else
- duration = (double)(2 * largest_pts - second_largest_pts) * param->i_timebase_num / param->i_timebase_den;
- + /* simpler than trying to use exact field timestamps */
- + if( param->b_field_encode )
- + duration *= 2;
- +
- i_end = x264_mdate();
- /* Erase progress indicator before printing encoding stats. */
- if( opt->b_progress )
- diff --git a/x264.h b/x264.h
- index b896f91..7549ea5 100644
- --- a/x264.h
- +++ b/x264.h
- @@ -309,7 +309,7 @@ typedef struct x264_param_t
- } vui;
- /* Bitstream parameters */
- - int i_frame_reference; /* Maximum number of reference frames */
- + int i_frame_reference; /* Maximum number of reference pictures */
- int i_dpb_size; /* Force a DPB size larger than that implied by B-frames and reference frames.
- * Useful in combination with interactive error resilience. */
- int i_keyint_max; /* Force an IDR keyframe at this interval */
- @@ -320,7 +320,7 @@ typedef struct x264_param_t
- int i_bframe; /* how many b-frame between 2 references pictures */
- int i_bframe_adaptive;
- int i_bframe_bias;
- - int i_bframe_pyramid; /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */
- + int i_bframe_pyramid; /* Keep some B-pictures as references: 0=off, 1=strict hierarchical, 2=normal */
- int b_open_gop;
- int b_bluray_compat;
- int i_avcintra_class;
- @@ -333,6 +333,7 @@ typedef struct x264_param_t
- int i_cabac_init_idc;
- int b_interlaced;
- + int b_field_encode; /* With field encoding, libx264 takes separate fields */
- int b_constrained_intra;
- int i_cqm_preset;
- @@ -456,8 +457,8 @@ typedef struct x264_param_t
- int b_vfr_input; /* VFR input. If 1, use timebase and timestamps for ratecontrol purposes.
- * If 0, use fps only. */
- int b_pulldown; /* use explicity set timebase for CFR */
- - uint32_t i_fps_num;
- - uint32_t i_fps_den;
- + uint32_t i_fps_num; /* Field rate when using field encoding mode, frame rate otherwise */
- + uint32_t i_fps_den; /* Field rate when using field encoding mode, frame rate otherwise */
- uint32_t i_timebase_num; /* Timebase numerator */
- uint32_t i_timebase_den; /* Timebase denominator */
- @@ -678,7 +679,8 @@ enum pic_struct_e
- {
- PIC_STRUCT_AUTO = 0, // automatically decide (default)
- PIC_STRUCT_PROGRESSIVE = 1, // progressive frame
- - // "TOP" and "BOTTOM" are not supported in x264 (PAFF only)
- + PIC_STRUCT_TOP = 2, // top field
- + PIC_STRUCT_BOTTOM = 3, // bottom field
- PIC_STRUCT_TOP_BOTTOM = 4, // top field followed by bottom
- PIC_STRUCT_BOTTOM_TOP = 5, // bottom field followed by top
- PIC_STRUCT_TOP_BOTTOM_TOP = 6, // top field, bottom field, top field repeated
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement