diff -NdurwBE x264-bluray/common/common.c x264-bluray3/common/common.c --- x264-bluray/common/common.c 2009-09-01 03:43:06 +0300 +++ x264-bluray3/common/common.c 2009-09-01 03:23:02 +0300 @@ -75,6 +75,7 @@ param->i_bframe_adaptive = X264_B_ADAPT_FAST; param->i_bframe_bias = 0; param->b_bframe_pyramid = 0; + param->b_strictdpb = 0; param->b_deblocking_filter = 1; param->i_deblocking_filter_alphac0 = 0; @@ -358,6 +359,8 @@ p->i_bframe_bias = atoi(value); OPT("b-pyramid") p->b_bframe_pyramid = atobool(value); + OPT("strict-dpb") + p->b_strictdpb = atobool(value); OPT("nf") p->b_deblocking_filter = !atobool(value); OPT2("filter", "deblock") @@ -381,6 +384,8 @@ p->i_slice_max_mbs = atoi(value); OPT("slices") p->i_slice_count = atoi(value); + OPT("open-gop") + p->b_open_gop = atobool(value); OPT("cabac") p->b_cabac = atobool(value); OPT("cabac-idc") @@ -881,6 +886,7 @@ s += sprintf( s, " cqm=%d", p->i_cqm_preset ); s += sprintf( s, " deadzone=%d,%d", p->analyse.i_luma_deadzone[0], p->analyse.i_luma_deadzone[1] ); s += sprintf( s, " chroma_qp_offset=%d", p->analyse.i_chroma_qp_offset ); + s += sprintf( s, " opengop=%d", p->b_open_gop ); s += sprintf( s, " threads=%d", p->i_threads ); if( p->i_slice_count ) s += sprintf( s, " slices=%d", p->i_slice_count ); @@ -895,8 +901,8 @@ s += sprintf( s, " bframes=%d", p->i_bframe ); if( p->i_bframe ) { - s += sprintf( s, " b_pyramid=%d b_adapt=%d b_bias=%d direct=%d wpredb=%d", - p->b_bframe_pyramid, p->i_bframe_adaptive, p->i_bframe_bias, + s += sprintf( s, " b_pyramid=%d b_strict_dpb=%d b_adapt=%d b_bias=%d direct=%d wpredb=%d", + p->b_bframe_pyramid, p->b_strictdpb, p->i_bframe_adaptive, p->i_bframe_bias, p->analyse.i_direct_mv_pred, p->analyse.b_weighted_bipred ); } diff -NdurwBE x264-bluray/common/common.h x264-bluray3/common/common.h --- x264-bluray/common/common.h 2009-09-01 03:43:06 +0300 +++ x264-bluray3/common/common.h 2009-09-01 03:21:31 +0300 @@ -224,6 +224,11 @@ int idc; int arg; } ref_pic_list_order[2][16]; + struct // for future expansion + { + int i_difference_of_pic_nums; + } mmco[16]; + int i_mmco_idx; int i_cabac_init_idc; @@ -366,7 +371,9 @@ /* frames used for reference + sentinels */ x264_frame_t *reference[16+2]; - int i_last_idr; /* Frame number of the last IDR */ + int i_last_idr; /* Frame number of the last IDR or RP */ + int i_idr_opengop_offset; /* Offset of above to handle open gop */ + int b_leading_bframes; /* Place holder to know when to remove old references for soft gop*/ int i_input; /* Number of input frames already accepted */ @@ -391,7 +398,11 @@ x264_frame_t *fref1[16+3]; /* ref list 1 */ int b_ref_reorder[2]; - + int i_mmco_idx; + struct + { + int i_difference_of_pic_nums; + } mmco[16]; /* Current MB DCT coeffs */ struct diff -NdurwBE x264-bluray/common/frame.h x264-bluray3/common/frame.h --- x264-bluray/common/frame.h 2009-09-01 03:43:06 +0300 +++ x264-bluray3/common/frame.h 2009-09-01 03:21:31 +0300 @@ -41,6 +41,7 @@ int i_frame; /* Presentation frame number */ int i_frame_num; /* Coded frame number */ int b_kept_as_ref; + int b_keyframe; float f_qp_avg_rc; /* QPs as decided by ratecontrol */ float f_qp_avg_aq; /* QPs as decided by AQ in addition to ratecontrol */ diff -NdurwBE x264-bluray/encoder/encoder.c x264-bluray3/encoder/encoder.c --- x264-bluray/encoder/encoder.c 2009-09-01 03:43:06 +0300 +++ x264-bluray3/encoder/encoder.c 2009-09-01 03:28:06 +0300 @@ -123,6 +123,16 @@ sh->b_ref_pic_list_reordering_l0 = h->b_ref_reorder[0]; sh->b_ref_pic_list_reordering_l1 = h->b_ref_reorder[1]; + sh->i_mmco_idx = h->i_mmco_idx; + if( h->i_mmco_idx ) + { + int j = 0; + for( ; j < h->i_mmco_idx; j++ ) + { + sh->mmco[j].i_difference_of_pic_nums = h->mmco[j].i_difference_of_pic_nums; + } + } + /* If the ref list isn't in the default order, construct reordering header */ /* List1 reordering isn't needed yet */ if( sh->b_ref_pic_list_reordering_l0 ) @@ -175,7 +185,7 @@ bs_write_ue( s, sh->i_type + 5 ); /* same type things */ bs_write_ue( s, sh->i_pps_id ); - bs_write( s, sh->sps->i_log2_max_frame_num, sh->i_frame_num ); + bs_write( s, sh->sps->i_log2_max_frame_num, sh->i_frame_num & (1<sps->i_log2_max_frame_num)-1 ); if( !sh->sps->b_frame_mbs_only ) { @@ -191,7 +201,7 @@ if( sh->sps->i_poc_type == 0 ) { - bs_write( s, sh->sps->i_log2_max_poc_lsb, sh->i_poc_lsb ); + bs_write( s, sh->sps->i_log2_max_poc_lsb, sh->i_poc_lsb & (1<sps->i_log2_max_poc_lsb)-1 ); if( sh->pps->b_pic_order && !sh->b_field_pic ) { bs_write_se( s, sh->i_delta_poc_bottom ); @@ -272,7 +282,17 @@ } else { - bs_write1( s, 0 ); /* adaptive_ref_pic_marking_mode_flag */ + bs_write1( s, sh->i_mmco_idx > 0 ); /* adaptive_ref_pic_marking_mode_flag */ + if( sh->i_mmco_idx > 0 ) + { + int i = 0; + for( ; i < sh->i_mmco_idx; i++ ) + { + bs_write_ue( s, 1 ); /* mark short term ref as unused */ + bs_write_ue( s, sh->mmco[i].i_difference_of_pic_nums - 1 ); + } + bs_write_ue( s, 0 ); + } } } @@ -838,6 +858,7 @@ h->frames.b_have_sub8x8_esa = !!(h->param.analyse.inter & X264_ANALYSE_PSUB8x8); h->frames.i_last_idr = - h->param.i_keyint_max; + h->frames.i_idr_opengop_offset = 0; //will stay 0 if !open-gop h->frames.i_input = 0; h->frames.last_nonb = NULL; @@ -1120,6 +1141,8 @@ h->b_ref_reorder[0] = 1; break; } + if( h->param.b_bframe_pyramid ) + h->b_ref_reorder[0] = 1; } h->i_ref1 = X264_MIN( h->i_ref1, h->frames.i_max_ref1 ); @@ -1254,6 +1277,43 @@ h->fenc->i_poc = 0; } +static inline void x264_reference_partial_reset( x264_t *h, int leave_one_nonbref_only ) +{ + int refs = 0; + int lastnonbidx = -1; + while( h->frames.reference[refs] ) + { + if( h->frames.reference[refs]->i_type == X264_TYPE_I + || h->frames.reference[refs]->i_type == X264_TYPE_IDR + || ( h->frames.reference[refs]->i_type == X264_TYPE_P + && !leave_one_nonbref_only) ) + lastnonbidx = refs; + refs++; + } + assert( lastnonbidx > -1 ); + while( refs > lastnonbidx+1 ) + { + int diff = h->i_frame_num - h->frames.reference[refs-1]->i_frame_num; + h->mmco[ h->i_mmco_idx++ ].i_difference_of_pic_nums = diff; + x264_frame_push_unused( h, x264_frame_pop( h->frames.reference ) ); + refs--; + } + // This makes room in the dpb for the delayed display time of the later b-frame's + // Within a mini-gop . Specific to b-pyramid. Also can remove all but one ref as well depending on + // leave_one_nonbref_only + while( ( h->param.b_strictdpb && ( ( refs + 2 ) > X264_MAX( h->frames.i_max_dpb, 4 ) ) + && h->sh.i_type == SLICE_TYPE_B + && !leave_one_nonbref_only ) + || ( lastnonbidx > 0 && leave_one_nonbref_only ) ) + { + int diff = h->i_frame_num - h->frames.reference[0]->i_frame_num; + h->mmco[ h->i_mmco_idx++ ].i_difference_of_pic_nums = diff; + x264_frame_push_unused( h, x264_frame_shift( h->frames.reference ) ); + lastnonbidx--; + refs--; + } +} + static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp ) { /* ------------------------ Create slice header ----------------------- */ @@ -1662,6 +1722,7 @@ x264_frame_expand_border_mod16( h, fenc ); fenc->i_frame = h->frames.i_input++; + h->i_mmco_idx = 0; x264_frame_push( h->frames.next, fenc ); @@ -1731,11 +1792,27 @@ if( h->fenc->param->param_free ) h->fenc->param->param_free( h->fenc->param ); } + int b_exceeds_min = (h->fenc->i_frame - h->frames.i_last_idr ) >= h->param.i_keyint_min; + h->fdec->b_keyframe = 0; + if( h->param.b_open_gop ) + { + if( ( (h->fenc->i_type == X264_TYPE_I && b_exceeds_min) + || h->fenc->i_type == X264_TYPE_IDR ) + && h->fenc->i_frame != 0 ) + { + h->frames.i_idr_opengop_offset += ( h->fenc->i_frame - h->frames.i_last_idr ); + h->fdec->b_keyframe = 1; + } + if( h->fenc->i_type == X264_TYPE_I && b_exceeds_min ) + h->frames.i_last_idr = h->fenc->i_frame; + } if( h->fenc->i_type == X264_TYPE_IDR ) { h->frames.i_last_idr = h->fenc->i_frame; + h->fdec->b_keyframe = 1; } + h->i_mmco_idx = 0; /* ------------------- Setup frame context ----------------------------- */ /* 5: Init data dependent of frame type */ @@ -1744,6 +1821,7 @@ /* reset ref pictures */ x264_reference_reset( h ); + h->frames.i_idr_opengop_offset = 0; i_nal_type = NAL_SLICE_IDR; i_nal_ref_idc = NAL_PRIORITY_HIGHEST; h->sh.i_type = SLICE_TYPE_I; @@ -1753,18 +1831,29 @@ 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_I; + if( ( h->fdec->b_keyframe && h->frames.b_leading_bframes ) || h->param.b_bframe_pyramid ) + x264_reference_partial_reset( h, h->frames.b_leading_bframes ); + if( h->param.b_open_gop ) + { + h->frames.b_leading_bframes = (b_exceeds_min && h->frames.b_leading_bframes) ? 1 : !b_exceeds_min ? 0 : 1; + } } else if( h->fenc->i_type == X264_TYPE_P ) { 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_partial_reset( h, h->frames.b_leading_bframes ); + if( h->frames.b_leading_bframes ) + h->frames.b_leading_bframes = 0; } else if( h->fenc->i_type == X264_TYPE_BREF ) { i_nal_type = NAL_SLICE; i_nal_ref_idc = NAL_PRIORITY_HIGH; /* maybe add MMCO to forget it? -> low */ h->sh.i_type = SLICE_TYPE_B; + if( h->param.b_strictdpb ) + x264_reference_partial_reset( h, 0 ); } else /* B frame */ { @@ -1774,7 +1863,7 @@ } h->fdec->i_poc = - h->fenc->i_poc = 2 * (h->fenc->i_frame - h->frames.i_last_idr); + h->fenc->i_poc = 2 * (h->fenc->i_frame - ( h->frames.i_last_idr - h->frames.i_idr_opengop_offset ) ); h->fdec->i_type = h->fenc->i_type; h->fdec->i_frame = h->fenc->i_frame; h->fenc->b_kept_as_ref = @@ -1845,7 +1934,8 @@ //clear payload tracking -- start here so we can add non VCL-NAL payload size //to bring to type II conformance h->out.i_frame_size = (NALU_OVERHEAD + 1 ) * (int)h->param.b_aud * (int)h->param.b_nal_hrd; - if( i_nal_type == NAL_SLICE_IDR && h->param.b_repeat_headers ) + if( (i_nal_type == NAL_SLICE_IDR && h->param.b_repeat_headers) + || ( h->sh.i_type == SLICE_TYPE_I && h->fdec->b_keyframe ) ) { /* generate sequence parameters */ x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST ); @@ -1860,6 +1950,13 @@ if( x264_nal_end( h ) ) return -1; h->out.i_frame_size += ( h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD ) * (int)h->param.b_nal_hrd; + /* recovery point */ + if( h->param.b_open_gop ) + { + x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE ); + x264_sei_recovery_point_write( h, &h->out.bs ); + x264_nal_end( h ); + } if( h->fenc->i_frame == 0 ) { @@ -1990,6 +2087,7 @@ pic_out->img.i_stride[i] = h->fdec->i_stride[i]; pic_out->img.plane[i] = h->fdec->plane[i]; } + pic_out->b_keyframe = h->fdec->b_keyframe; /* ---------------------- Update encoder state ------------------------- */ diff -NdurwBE x264-bluray/encoder/set.c x264-bluray3/encoder/set.c --- x264-bluray/encoder/set.c 2009-09-01 03:43:06 +0300 +++ x264-bluray3/encoder/set.c 2009-09-01 03:21:31 +0300 @@ -77,6 +77,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { sps->i_id = i_id; + int max_frame_num; sps->b_qpprime_y_zero_transform_bypass = param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0; if( sps->b_qpprime_y_zero_transform_bypass ) @@ -96,17 +97,26 @@ /* Never set constraint_set2, it is not necessary and not used in real world. */ sps->b_constraint_set2 = 0; - sps->i_log2_max_frame_num = 4; /* at least 4 */ - while( (1 << sps->i_log2_max_frame_num) <= param->i_keyint_max ) - { + sps->vui.i_num_reorder_frames = param->b_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; + /* 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(16, X264_MAX(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames)); + + /* number of refs + current frame */ + /* we MMCO away b-refs, so we have to count those too. */ + max_frame_num = sps->i_num_ref_frames * (param->b_bframe_pyramid?2:1) + 1; + sps->i_log2_max_frame_num = 4; + while( (1 << sps->i_log2_max_frame_num) < max_frame_num ) sps->i_log2_max_frame_num++; - } - sps->i_log2_max_frame_num++; /* just in case */ sps->i_poc_type = 0; if( sps->i_poc_type == 0 ) { - sps->i_log2_max_poc_lsb = sps->i_log2_max_frame_num + 1; /* max poc = 2*frame_num */ + int max_poc = (param->i_bframe+1)*(param->b_bframe_pyramid?3:2)*2; + sps->i_log2_max_poc_lsb = 4; + while( (1 << sps->i_log2_max_poc_lsb) < max_poc ) + sps->i_log2_max_poc_lsb++; } else if( sps->i_poc_type == 1 ) { @@ -193,12 +203,6 @@ sps->vui.b_fixed_frame_rate = 1; } - sps->vui.i_num_reorder_frames = param->b_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; - /* 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(16, X264_MAX(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames)); - sps->vui.b_bitstream_restriction = 1; if( sps->vui.b_bitstream_restriction ) { @@ -545,6 +549,22 @@ bs_rbsp_trailing( s ); } +void x264_sei_recovery_point_write( x264_t *h, bs_t *s ) +{ + int payload_size; + + bs_write( s, 8, 0x06 ); // payload_type = Recovery Point + payload_size = 1 ; // values as given below will never be > 1 + + bs_write( s, 8, (payload_size + 7) / 8); + bs_write_ue( s, 0 ); // recovery_frame_cnt 0 + bs_write( s, 1, 1 ); //exact_match_flag 1 + bs_write( s, 1, 0 ); //broken_link_flag 0 + bs_write( s, 2, 0 ); //changing_slice_group 0 + + bs_align_10( s ); +} + int x264_sei_version_write( x264_t *h, bs_t *s ) { int i; diff -NdurwBE x264-bluray/encoder/set.h x264-bluray3/encoder/set.h --- x264-bluray/encoder/set.h 2009-09-01 03:43:06 +0300 +++ x264-bluray3/encoder/set.h 2009-09-01 03:21:31 +0300 @@ -24,6 +24,7 @@ #ifndef X264_ENCODER_SET_H #define X264_ENCODER_SET_H +void x264_sei_recovery_point_write( x264_t *h, bs_t *s ); void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ); void x264_sps_write( bs_t *s, x264_sps_t *sps ); void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *sps ); diff -NdurwBE x264-bluray/encoder/slicetype.c x264-bluray3/encoder/slicetype.c --- x264-bluray/encoder/slicetype.c 2009-09-01 03:42:50 +0300 +++ x264-bluray3/encoder/slicetype.c 2009-09-01 03:30:26 +0300 @@ -704,6 +704,7 @@ { x264_mb_analysis_t a; x264_frame_t *frames[X264_LOOKAHEAD_MAX+3] = { NULL, }; + int minigop_end_frame_type[X264_LOOKAHEAD_MAX+3]; int num_frames; int keyint_limit; int i,j; @@ -717,7 +718,11 @@ return; frames[0] = h->frames.last_nonb; for( j = 0; h->frames.next[j] && h->frames.next[j]->i_type == X264_TYPE_AUTO; j++ ) + { frames[j+1] = h->frames.next[j]; + minigop_end_frame_type[j+1] = frames[j+1]->i_frame - h->frames.i_last_idr + >= h->param.i_keyint_max ? X264_TYPE_I : X264_TYPE_P; + } if( !j ) return; @@ -726,7 +731,8 @@ num_frames = X264_MIN( j, keyint_limit ); x264_lowres_context_init( h, &a ); - idr_frame_type = frames[1]->i_frame - h->frames.i_last_idr >= h->param.i_keyint_min ? X264_TYPE_IDR : X264_TYPE_I; + idr_frame_type = frames[1]->i_frame - h->frames.i_last_idr >= h->param.i_keyint_min ? + ( h->param.b_open_gop && h->frames.i_last_idr > -1 ? X264_TYPE_I : X264_TYPE_IDR ) : X264_TYPE_I; /* This is important psy-wise: if we have a non-scenecut keyframe, * there will be significant visual artifacts if the frames just before @@ -736,7 +742,7 @@ num_frames = j; else if( num_frames == 1 ) { - frames[1]->i_type = X264_TYPE_P; + frames[1]->i_type = minigop_end_frame_type[1]; if( h->param.i_scenecut_threshold && scenecut( h, &a, frames, 0, 1 ) ) frames[1]->i_type = idr_frame_type; return; @@ -771,9 +777,9 @@ num_bframes = strspn( best_paths[num_frames-2], "B" ); /* Load the results of the analysis into the frame types. */ for( j = 1; j < num_frames; j++ ) - frames[j]->i_type = best_paths[num_frames-2][j-1] == 'B' ? X264_TYPE_B : X264_TYPE_P; + frames[j]->i_type = best_paths[num_frames-2][j-1] == 'B' ? X264_TYPE_B : minigop_end_frame_type[j]; } - frames[num_frames]->i_type = X264_TYPE_P; + frames[num_frames]->i_type = minigop_end_frame_type[num_frames]; } else if( h->param.i_bframe_adaptive == X264_B_ADAPT_FAST ) { @@ -783,7 +789,7 @@ if( frames[i+2]->i_intra_mbs[2] > i_mb_count / 2 ) { frames[i+1]->i_type = X264_TYPE_P; - frames[i+2]->i_type = X264_TYPE_P; + frames[i+2]->i_type = minigop_end_frame_type[i+2]; i += 2; continue; } @@ -795,7 +801,7 @@ if( cost1p0 + cost2p0 < cost1b1 + cost2p1 ) { frames[i+1]->i_type = X264_TYPE_P; - frames[i+2]->i_type = X264_TYPE_P; + frames[i+2]->i_type = minigop_end_frame_type[i+2]; i += 2; continue; } @@ -804,7 +810,7 @@ #define INTER_THRESH 300 #define P_SENS_BIAS (50 - h->param.i_bframe_bias) frames[i+1]->i_type = X264_TYPE_B; - frames[i+2]->i_type = X264_TYPE_P; + frames[i+2]->i_type = minigop_end_frame_type[i+2]; for( j = i+2; j <= X264_MIN( h->param.i_bframe, num_frames-1 ); j++ ) { @@ -813,7 +819,7 @@ if( pcost > pthresh*i_mb_count || frames[j+1]->i_intra_mbs[j-i+1] > i_mb_count/3 ) { - frames[j]->i_type = X264_TYPE_P; + frames[j]->i_type = minigop_end_frame_type[j]; break; } else @@ -821,7 +827,7 @@ } i = j; } - frames[i+!i]->i_type = X264_TYPE_P; + frames[i+!i]->i_type = minigop_end_frame_type[i+!i]; num_bframes = 0; while( num_bframes < num_frames && frames[num_bframes+1]->i_type == X264_TYPE_B ) num_bframes++; @@ -830,15 +836,15 @@ { num_bframes = X264_MIN(num_frames-1, h->param.i_bframe); for( j = 1; j < num_frames; j++ ) - frames[j]->i_type = (j%(num_bframes+1)) ? X264_TYPE_B : X264_TYPE_P; - frames[num_frames]->i_type = X264_TYPE_P; + frames[j]->i_type = (j%(num_bframes+1)) ? X264_TYPE_B : minigop_end_frame_type[j]; + frames[num_frames]->i_type = minigop_end_frame_type[num_frames]; } /* Check scenecut on the first minigop. */ for( j = 1; j < num_bframes+1; j++ ) if( h->param.i_scenecut_threshold && scenecut( h, &a, frames, j, j+1 ) ) { - frames[j]->i_type = X264_TYPE_P; + frames[j]->i_type = minigop_end_frame_type[j]; num_analysed_frames = j; break; } @@ -848,7 +854,7 @@ else { for( j = 1; j < num_frames; j++ ) - frames[j]->i_type = X264_TYPE_P; + frames[j]->i_type = minigop_end_frame_type[j]; reset_start = !keyframe + 1; num_bframes = 0; } @@ -867,9 +873,9 @@ { if( ((j-keyint_limit) % h->param.i_keyint_max) == 0 ) { - if( j && h->param.i_keyint_max > 1 ) - frames[j]->i_type = X264_TYPE_P; - frames[j+1]->i_type = X264_TYPE_IDR; + //if( j && h->param.i_keyint_max > 1 ) + // frames[j]->i_type = X264_TYPE_P; + frames[j+1]->i_type = minigop_end_frame_type[j+1]; reset_start = X264_MIN( reset_start, j+2 ); } } @@ -912,12 +917,15 @@ if( frm->i_frame - h->frames.i_last_idr >= h->param.i_keyint_max ) { if( frm->i_type == X264_TYPE_AUTO ) - frm->i_type = X264_TYPE_IDR; - if( frm->i_type != X264_TYPE_IDR ) + frm->i_type = h->param.b_open_gop && h->frames.i_last_idr > -1 ? X264_TYPE_I : X264_TYPE_IDR; + if( frm->i_type != X264_TYPE_I && frm->i_type != X264_TYPE_IDR ) x264_log( h, X264_LOG_WARNING, "specified frame type (%d) is not compatible with keyframe interval\n", frm->i_type ); } - if( frm->i_type == X264_TYPE_IDR ) + if( ( frm->i_type == X264_TYPE_I || frm->i_type == X264_TYPE_IDR ) + && !(frm->i_frame - h->frames.i_last_idr < h->param.i_keyint_min) + && !h->param.b_open_gop ) { + frm->i_type = X264_TYPE_IDR; /* Close GOP */ if( bframes > 0 ) { diff -NdurwBE x264-bluray/muxers.c x264-bluray3/muxers.c --- x264-bluray/muxers.c 2009-09-01 03:42:50 +0300 +++ x264-bluray3/muxers.c 2009-09-01 03:21:31 +0300 @@ -800,7 +800,7 @@ uint64_t pts = (uint64_t)p_picture->i_pts; int32_t offset = p_mp4->i_init_delay + pts - dts; - p_mp4->p_sample->IsRAP = p_picture->i_type == X264_TYPE_IDR ? 1 : 0; + p_mp4->p_sample->IsRAP = p_picture->b_keyframe; p_mp4->p_sample->DTS = dts; p_mp4->p_sample->CTS_Offset = offset; gf_isom_add_sample(p_mp4->p_file, p_mp4->i_track, p_mp4->i_descidx, p_mp4->p_sample); @@ -1016,8 +1016,7 @@ p_mkv->b_writing_frame = 0; - return mk_setFrameFlags( p_mkv->w, i_stamp, - p_picture->i_type == X264_TYPE_IDR ); + return mk_setFrameFlags( p_mkv->w, i_stamp, p_picture->b_keyframe ); } int close_file_mkv( hnd_t handle ) diff -NdurwBE x264-bluray/x264.c x264-bluray3/x264.c --- x264-bluray/x264.c 2009-09-01 03:43:06 +0300 +++ x264-bluray3/x264.c 2009-09-01 03:21:31 +0300 @@ -191,6 +191,8 @@ " - 2: Optimal (slow with high --bframes)\n", defaults->i_bframe_adaptive ); H1( " --b-bias Influences how often B-frames are used [%d]\n", defaults->i_bframe_bias ); H0( " --b-pyramid Keep some B-frames as references\n" ); + H0( " --strict-dpb Stricter usage of dpb when b-pyramid is active (ref 4+)\n" ); + H0( " --open-gop Use non IDR i-frames at max-keyint w/ recovery pt SEI\n" ); H0( " --no-cabac Disable CABAC\n" ); H0( " -r, --ref Number of reference frames [%d]\n", defaults->i_frame_reference ); H1( " --no-deblock Disable loop filter\n" ); @@ -400,9 +402,11 @@ { "no-b-adapt", no_argument, NULL, 0 }, { "b-bias", required_argument, NULL, 0 }, { "b-pyramid", no_argument, NULL, 0 }, + { "strict-dpb", no_argument, NULL, 0 }, { "min-keyint", required_argument, NULL, 'i' }, { "keyint", required_argument, NULL, 'I' }, { "scenecut", required_argument, NULL, 0 }, + { "open-gop", no_argument, NULL, 0 }, { "no-scenecut", no_argument, NULL, 0 }, { "nf", no_argument, NULL, 0 }, { "no-deblock", no_argument, NULL, 0 }, diff -NdurwBE x264-bluray/x264.h x264-bluray3/x264.h --- x264-bluray/x264.h 2009-09-01 03:43:06 +0300 +++ x264-bluray3/x264.h 2009-09-01 03:21:31 +0300 @@ -195,6 +195,8 @@ int i_bframe_adaptive; int i_bframe_bias; int b_bframe_pyramid; /* Keep some B-frames as references */ + int b_strictdpb; /* Reserve a spot in dpb for delayed display time b frames */ + int b_open_gop; int b_deblocking_filter; int i_deblocking_filter_alphac0; /* [-6, 6] -6 light filter, 6 strong */ @@ -370,6 +372,7 @@ int i_type; /* In: force quantizer for > 0 */ int i_qpplus1; + int b_keyframe; /* In: user pts, Out: pts of encoded picture (user)*/ int64_t i_pts; /* In: custom encoding parameters to be set from this frame forwards