diff options
-rw-r--r-- | libhb/common.c | 3 | ||||
-rw-r--r-- | libhb/common.h | 2 | ||||
-rw-r--r-- | libhb/encavcodec.c | 16 | ||||
-rw-r--r-- | libhb/enctheora.c | 34 | ||||
-rw-r--r-- | libhb/encx264.c | 42 | ||||
-rw-r--r-- | libhb/hb.h | 4 | ||||
-rw-r--r-- | libhb/muxmkv.c | 15 | ||||
-rw-r--r-- | libhb/render.c | 9 | ||||
-rw-r--r-- | libhb/work.c | 45 |
9 files changed, 102 insertions, 68 deletions
diff --git a/libhb/common.c b/libhb/common.c index 06fb00645..2387aa4ef 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -520,9 +520,8 @@ int hb_calc_bitrate( hb_job_t * job, int size ) if( size == -1 ) { - hb_interjob_t * interjob = hb_interjob_get( job->h ); avail = job->vbitrate * 125 * length; - avail += length * interjob->vrate * overhead / interjob->vrate_base; + avail += length * job->vrate * overhead / job->vrate_base; } /* Video overhead */ diff --git a/libhb/common.h b/libhb/common.h index bd1eaddc8..031b8b642 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -230,6 +230,8 @@ struct hb_job_s int vcodec; float vquality; int vbitrate; + int pfr_vrate; + int pfr_vrate_base; int vrate; int vrate_base; int vfr; diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c index eaf7b7020..07fc748a8 100644 --- a/libhb/encavcodec.c +++ b/libhb/encavcodec.c @@ -77,8 +77,18 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) } context->width = job->width; context->height = job->height; - rate_num = job->vrate_base; - rate_den = job->vrate; + + if( job->pass == 2 ) + { + hb_interjob_t * interjob = hb_interjob_get( job->h ); + rate_num = interjob->vrate_base; + rate_den = interjob->vrate; + } + else + { + rate_num = job->vrate_base; + rate_den = job->vrate; + } if (rate_den == 27000000) { int ii; @@ -103,7 +113,7 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) rate_den >>= 1; } context->time_base = (AVRational) { rate_num, rate_den }; - context->gop_size = 10 * job->vrate / job->vrate_base; + context->gop_size = 10 * (int)( (double)job->vrate / (double)job->vrate_base + 0.5 ); context->pix_fmt = PIX_FMT_YUV420P; if( job->anamorphic.mode ) diff --git a/libhb/enctheora.c b/libhb/enctheora.c index 042262c76..2ced60693 100644 --- a/libhb/enctheora.c +++ b/libhb/enctheora.c @@ -66,8 +66,17 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) ti.frame_height = (job->height + 0xf) & ~0xf; ti.pic_x = ti.pic_y = 0; - ti.fps_numerator = job->vrate; - ti.fps_denominator = job->vrate_base; + if( job->pass == 2 ) + { + hb_interjob_t * interjob = hb_interjob_get( job->h ); + ti.fps_numerator = interjob->vrate; + ti.fps_denominator = interjob->vrate_base; + } + else + { + ti.fps_numerator = job->vrate; + ti.fps_denominator = job->vrate_base; + } if( job->anamorphic.mode ) { ti.aspect_numerator = job->anamorphic.par_width; @@ -98,30 +107,13 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) } } - if ( job->pass == 2 && !job->cfr ) - { - /* Even though the framerate might be different due to VFR, - we still want the same keyframe intervals as the 1st pass, - so the 1st pass stats won't conflict on frame decisions. */ - hb_interjob_t * interjob = hb_interjob_get( job->h ); - keyframe_frequency = ( 10 * interjob->vrate / interjob->vrate_base ) + 1; - } - else - { - int fps = job->vrate / job->vrate_base; + keyframe_frequency = 10 * (int)( (double)job->vrate / (double)job->vrate_base + 0.5 ); - /* adjust +1 when fps has remainder to bump - { 23.976, 29.976, 59.94 } to { 24, 30, 60 } */ - if (job->vrate % job->vrate_base) - fps += 1; + hb_log("theora: keyint: %i", keyframe_frequency); - keyframe_frequency = fps * 10; - } int tmp = keyframe_frequency - 1; for (log_keyframe = 0; tmp; log_keyframe++) tmp >>= 1; - - hb_log("theora: keyint: %i", keyframe_frequency); ti.keyframe_granule_shift = log_keyframe; diff --git a/libhb/encx264.c b/libhb/encx264.c index 270692c8a..2c64321ba 100644 --- a/libhb/encx264.c +++ b/libhb/encx264.c @@ -98,8 +98,17 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) param.i_threads = ( hb_get_cpu_count() * 3 / 2 ); param.i_width = job->width; param.i_height = job->height; - param.i_fps_num = job->vrate; - param.i_fps_den = job->vrate_base; + if( job->pass == 2 ) + { + hb_interjob_t * interjob = hb_interjob_get( job->h ); + param.i_fps_num = interjob->vrate; + param.i_fps_den = interjob->vrate_base; + } + else + { + param.i_fps_num = job->vrate; + param.i_fps_den = job->vrate_base; + } if ( job->cfr == 1 ) { param.i_timebase_num = 0; @@ -115,26 +124,11 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) /* Disable annexb. Inserts size into nal header instead of start code */ param.b_annexb = 0; - /* Set min:max key intervals ratio to 1:10 of fps. - * This section is skipped if fps=25 (default). - */ - if (job->vrate_base != 1080000) - { - if (job->pass == 2 && !job->cfr ) - { - /* Even though the framerate might be different due to VFR, - we still want the same keyframe intervals as the 1st pass, - so the 1st pass stats won't conflict on frame decisions. */ - hb_interjob_t * interjob = hb_interjob_get( job->h ); - param.i_keyint_max = 10 * (int)( (double)interjob->vrate / (double)interjob->vrate_base + 0.5 ); - } - else - { - /* adjust +0.5 for when fps has remainder to bump - { 23.976, 29.976, 59.94 } to { 24, 30, 60 } */ - param.i_keyint_max = 10 * (int)( (double)job->vrate / (double)job->vrate_base + 0.5 ); - } - } + /* Set min:max keyframe intervals to 1:10 of fps. + adjust +0.5 for when fps has remainder to bump + { 23.976, 29.976, 59.94 } to { 24, 30, 60 } */ + param.i_keyint_min = (int)( (double)job->vrate / (double)job->vrate_base + 0.5 ); + param.i_keyint_max = 10 * param.i_keyint_min; param.i_log_level = X264_LOG_INFO; @@ -211,7 +205,9 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) job->areBframes = 0; } - if( param.i_keyint_min != X264_KEYINT_MIN_AUTO || param.i_keyint_max != 250 ) + /* For 25 fps sources, HandBrake's explicit keyints will match the x264 defaults: + min-keyint 25 (same as auto), keyint 250 */ + if( param.i_keyint_min != 25 || param.i_keyint_max != 250 ) { int min_auto; diff --git a/libhb/hb.h b/libhb/hb.h index 38634b2a5..56566f330 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -82,8 +82,8 @@ typedef struct hb_interjob_s int frame_count; /* number of frames counted by sync */ uint64_t total_time; /* real length in 90khz (i.e. / 90000 */ int render_dropped; /* frames droped by telecine */ - int vrate; /* initial assigned vrate */ - int vrate_base; /* initial assigned vrate_base */ + int vrate; /* actual measured output vrate from 1st pass */ + int vrate_base; /* actual measured output vrate_base from 1st pass */ hb_subtitle_t *select_subtitle; /* foreign language scan subtitle */ } hb_interjob_t; diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index 073b39f45..f169e3de1 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -148,8 +148,19 @@ static int MKVInit( hb_mux_object_t * m ) track->extra.video.displayWidth = job->width; } - - track->defaultDuration = (int64_t)(((float)job->vrate_base / (float)job->vrate) * 1000000000); + int vrate_base, vrate; + if( job->pass == 2 ) + { + hb_interjob_t * interjob = hb_interjob_get( job->h ); + vrate_base = interjob->vrate_base; + vrate = interjob->vrate; + } + else + { + vrate_base = job->vrate_base; + vrate = job->vrate; + } + track->defaultDuration = (int64_t)(((float)vrate_base / (float)vrate) * 1000000000); mux_data->track = mk_createTrack(m->file, track); diff --git a/libhb/render.c b/libhb/render.c index c16b9403d..0af7148c1 100644 --- a/libhb/render.c +++ b/libhb/render.c @@ -779,7 +779,14 @@ int renderInit( hb_work_object_t * w, hb_job_t * job ) pv->chapter_time = 0; pv->chapter_val = 0; - pv->frame_rate = (double)job->vrate_base * (1./300.); + if ( job->cfr == 2 ) + { + pv->frame_rate = (double)job->pfr_vrate_base * (1./300.); + } + else + { + pv->frame_rate = (double)job->vrate_base * (1./300.); + } /* Setup filters */ /* TODO: Move to work.c? */ diff --git a/libhb/work.c b/libhb/work.c index d05a22aa7..a5f0e7418 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -200,20 +200,23 @@ void hb_display_job_info( hb_job_t * job ) hb_log( " + bitrate %d kbps", title->video_bitrate / 1000 ); } - if( !job->cfr ) + if( job->cfr == 0 ) { hb_log( " + frame rate: same as source (around %.3f fps)", (float) title->rate / (float) title->rate_base ); } - else + else if( job->cfr == 1 ) { - static const char *frtypes[] = { - "", "constant", "peak rate limited to" - }; - hb_log( " + frame rate: %.3f fps -> %s %.3f fps", - (float) title->rate / (float) title->rate_base, frtypes[job->cfr], + hb_log( " + frame rate: %.3f fps -> constant %.3f fps", + (float) title->rate / (float) title->rate_base, (float) job->vrate / (float) job->vrate_base ); } + else if( job->cfr == 2 ) + { + hb_log( " + frame rate: %.3f fps -> peak rate limited to %.3f fps", + (float) title->rate / (float) title->rate_base, + (float) job->pfr_vrate / (float) job->pfr_vrate_base ); + } if( job->anamorphic.mode ) { @@ -380,13 +383,11 @@ void correct_framerate( hb_job_t * job ) if( ( job->sequence_id & 0xFFFFFF ) != ( interjob->last_job & 0xFFFFFF) ) return; // Interjob information is for a different encode. - /* Cache the original framerate before altering it. */ - interjob->vrate = job->vrate; - interjob->vrate_base = job->vrate_base; - + // compute actual output vrate from first pass real_frames = interjob->frame_count - interjob->render_dropped; - job->vrate = job->vrate_base * ( (double)real_frames * 90000 / interjob->total_time ); + interjob->vrate = job->vrate_base * ( (double)real_frames * 90000 / interjob->total_time ); + interjob->vrate_base = job->vrate_base; } static int check_ff_audio( hb_list_t *list_audio, hb_audio_t *ff_audio ) @@ -442,7 +443,7 @@ static void do_job( hb_job_t * job ) title = job->title; interjob = hb_interjob_get( job->h ); - if( job->pass == 2 && !job->cfr ) + if( job->pass == 2 ) { correct_framerate( job ); } @@ -492,8 +493,25 @@ static void do_job( hb_job_t * job ) if ( job->cfr == 0 ) { /* Ensure we're using "Same as source" FPS */ + job->vrate = title->rate; job->vrate_base = title->rate_base; } + else if ( job->cfr == 2 ) + { + job->pfr_vrate = job->vrate; + job->pfr_vrate_base = job->vrate_base; + + // Ensure we're using "Same as source" FPS, with peak set by pfr_vrate_* + // For PFR, we want the framerate based on the source's actual + // framerate, unless it's higher than the specified peak framerate. + double source_fps = (double)job->title->rate / job->title->rate_base; + double peak_l_fps = (double)job->vrate / job->vrate_base; + if ( source_fps < peak_l_fps ) + { + job->vrate_base = title->rate_base; + job->vrate = title->rate; + } + } job->fifo_mpeg2 = hb_fifo_init( FIFO_LARGE, FIFO_LARGE_WAKE ); job->fifo_raw = hb_fifo_init( FIFO_SMALL, FIFO_SMALL_WAKE ); @@ -1221,7 +1239,6 @@ static void work_loop( void * _w ) } break; } - // Invalidate buf_out so that if there is no output // we don't try to pass along junk. buf_out = NULL; |