summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
Diffstat (limited to 'libhb')
-rw-r--r--libhb/common.c3
-rw-r--r--libhb/common.h2
-rw-r--r--libhb/encavcodec.c16
-rw-r--r--libhb/enctheora.c34
-rw-r--r--libhb/encx264.c42
-rw-r--r--libhb/hb.h4
-rw-r--r--libhb/muxmkv.c15
-rw-r--r--libhb/render.c9
-rw-r--r--libhb/work.c45
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;