diff options
author | jbrjake <[email protected]> | 2007-11-10 01:51:36 +0000 |
---|---|---|
committer | jbrjake <[email protected]> | 2007-11-10 01:51:36 +0000 |
commit | d95e8d52105a29a03750232c47949b37dc3075dc (patch) | |
tree | 94e4f7b25d65b692259241c7049dede3c9568ab7 /libhb/render.c | |
parent | 5e6725417750adb69ccbca26d1c7cbdbfd4fd142 (diff) |
First attempt at variable frame rate detelecining for NTSC video sources.
This check-in includes the library code as well as the CLI implementation.
Only works with MP4 and MKV, untested with high profile, results may vary with mixed content, consult a physician if condition persists for longer than four hours.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1051 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/render.c')
-rw-r--r-- | libhb/render.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/libhb/render.c b/libhb/render.c index edbd18a80..07f38897e 100644 --- a/libhb/render.c +++ b/libhb/render.c @@ -19,6 +19,10 @@ struct hb_work_private_s AVPicture pic_tmp_out; hb_buffer_t * buf_scale; hb_fifo_t * subtitle_queue; + hb_fifo_t * delay_queue; + int frames_to_extend; + int dropped_frames; + int extended_frames; }; int renderInit( hb_work_object_t *, hb_job_t * ); @@ -153,10 +157,14 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_job_t * job = pv->job; hb_title_t * title = job->title; hb_buffer_t * in = *buf_in, * buf_tmp_in = *buf_in; + hb_buffer_t * ivtc_buffer = NULL; if(!in->data) { - /* If the input buffer is end of stream, send out an empty one to the next stage as well. */ + /* If the input buffer is end of stream, send out an empty one + * to the next stage as well. Note that this will result in us + * losing the current contents of the delay queue. + */ *buf_out = hb_buffer_init(0); return HB_WORK_OK; } @@ -227,6 +235,11 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in, { hb_fifo_get( pv->subtitle_queue ); buf_tmp_in = NULL; + if( job->vfr ) + { + pv->frames_to_extend += 4; + pv->dropped_frames++; + } break; } } @@ -291,6 +304,49 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in, memcpy( buf_render->data, buf_tmp_in->data, buf_render->size ); hb_buffer_copy_settings( buf_render, buf_tmp_in ); } + + if (*buf_out) + { + hb_fifo_push( pv->delay_queue, *buf_out ); + *buf_out = NULL; + } + + /* + * Keep the last three frames in our queue, this ensures that we have the last + * two always in there should we need to rewrite the durations on them. + */ + if( hb_fifo_size( pv->delay_queue ) >= 3 ) + { + *buf_out = hb_fifo_get( pv->delay_queue ); + } + + if( *buf_out ) + { + if( pv->frames_to_extend ) + { + /* + * A frame's been dropped by VFR detelecine. + * Gotta make up the lost time. This will also + * slow down the video to 23.976fps. + * The dropped frame ran for 3003 ticks, so + * divvy it up amongst the 4 frames left behind. + * This is what the delay_queue is for; + * telecined sequences start 2 frames before + * the dropped frame, so to slow down the right + * ones you need a 2 frame delay between + * reading input and writing output. + */ + ivtc_buffer = *buf_out; + + if (pv->frames_to_extend % 4) + ivtc_buffer->stop += 751; + else + ivtc_buffer->stop += 750; + + pv->frames_to_extend--; + pv->extended_frames++; + } + } return HB_WORK_OK; } @@ -299,12 +355,21 @@ void renderClose( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; + hb_log("render: dropped frames: %i (%i ticks)", pv->dropped_frames, (pv->dropped_frames * 3003) ); + hb_log("render: extended frames: %i (%i ticks)", pv->extended_frames, ( ( pv->extended_frames / 4 ) * 3003 ) ); + hb_log("render: Lost time: %i frames (%i ticks)", (pv->dropped_frames * 4) - (pv->extended_frames), (pv->dropped_frames * 3003) - ( ( pv->extended_frames / 4 ) * 3003 ) ); + /* Cleanup subtitle queue */ if( pv->subtitle_queue ) { hb_fifo_close( &pv->subtitle_queue ); } + if( pv->delay_queue ) + { + hb_fifo_close( &pv->delay_queue ); + } + /* Cleanup filters */ /* TODO: Move to work.c? */ if( pv->job->filters ) @@ -352,6 +417,10 @@ int renderInit( hb_work_object_t * w, hb_job_t * job ) /* Setup FIFO queue for subtitle cache */ pv->subtitle_queue = hb_fifo_init( 8 ); + pv->delay_queue = hb_fifo_init( 8 ); + pv->frames_to_extend = 0; + pv->dropped_frames = 0; + pv->extended_frames = 0; /* Setup filters */ /* TODO: Move to work.c? */ |