diff options
author | John Stebbins <[email protected]> | 2017-04-15 13:20:21 -0600 |
---|---|---|
committer | John Stebbins <[email protected]> | 2017-04-15 13:22:55 -0600 |
commit | bb92ab00e37bdb87b528b1901d956c1f24417387 (patch) | |
tree | f327eb191c83b6ffad38ad32c8d144f6b0582ee5 /libhb | |
parent | 52d4c21b22cfc91b63a680aa7e475cc0ca6012cb (diff) |
decsrt: fix p-to-p start time after seeking
Reader can skip data at the beginning of the file. We were not
informing decsrt how much was skipped when pts_to_start caused the skip.
Fixes https://forum.handbrake.fr/viewtopic.php?f=11&t=36258
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.h | 4 | ||||
-rw-r--r-- | libhb/decsrtsub.c | 150 | ||||
-rw-r--r-- | libhb/reader.c | 16 | ||||
-rw-r--r-- | libhb/sync.c | 29 | ||||
-rw-r--r-- | libhb/work.c | 7 |
5 files changed, 130 insertions, 76 deletions
diff --git a/libhb/common.h b/libhb/common.h index a9bc3d412..266f13fe2 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -671,6 +671,10 @@ struct hb_job_s hb_esconfig_t config; hb_mux_data_t * mux_data; + + int64_t reader_pts_offset; // Reader can discard some video. + // Other pipeline stages need to know + // this. E.g. sync and decsrtsub #endif }; diff --git a/libhb/decsrtsub.c b/libhb/decsrtsub.c index a36461203..f6b3fc28c 100644 --- a/libhb/decsrtsub.c +++ b/libhb/decsrtsub.c @@ -601,85 +601,100 @@ static hb_buffer_t *srt_read( hb_work_private_t *pv ) static int decsrtInit( hb_work_object_t * w, hb_job_t * job ) { - int retval = 1; hb_work_private_t * pv; int i; hb_chapter_t * chapter; pv = calloc( 1, sizeof( hb_work_private_t ) ); - if( pv ) + if (pv == NULL) { - w->private_data = pv; - - pv->job = job; - pv->current_state = k_state_potential_new_entry; - pv->number_of_entries = 0; - pv->last_entry_number = 0; - pv->current_time = 0; - pv->subtitle = w->subtitle; - - /* - * Figure out the start and stop times from teh chapters being - * encoded - drop subtitle not in this range. - */ - pv->start_time = 0; - for( i = 1; i < job->chapter_start; ++i ) + goto fail; + } + + w->private_data = pv; + + pv->job = job; + pv->current_state = k_state_potential_new_entry; + pv->number_of_entries = 0; + pv->last_entry_number = 0; + pv->current_time = 0; + pv->subtitle = w->subtitle; + + /* + * Figure out the start and stop times from teh chapters being + * encoded - drop subtitle not in this range. + */ + pv->start_time = 0; + for( i = 1; i < job->chapter_start; ++i ) + { + chapter = hb_list_item( job->list_chapter, i - 1 ); + if( chapter ) { - chapter = hb_list_item( job->list_chapter, i - 1 ); - if( chapter ) - { - pv->start_time += chapter->duration; - } else { - hb_error( "Could not locate chapter %d for SRT start time", i ); - retval = 0; - } + pv->start_time += chapter->duration; + } else { + hb_error( "Could not locate chapter %d for SRT start time", i ); } - pv->stop_time = pv->start_time; - for( i = job->chapter_start; i <= job->chapter_end; ++i ) + } + pv->stop_time = pv->start_time; + for( i = job->chapter_start; i <= job->chapter_end; ++i ) + { + chapter = hb_list_item( job->list_chapter, i - 1 ); + if( chapter ) { - chapter = hb_list_item( job->list_chapter, i - 1 ); - if( chapter ) - { - pv->stop_time += chapter->duration; - } else { - hb_error( "Could not locate chapter %d for SRT start time", i ); - retval = 0; - } + pv->stop_time += chapter->duration; + } else { + hb_error( "Could not locate chapter %d for SRT start time", i ); } + } - hb_deep_log( 3, "SRT Start time %"PRId64", stop time %"PRId64, pv->start_time, pv->stop_time); - - pv->iconv_context = iconv_open( "utf-8", pv->subtitle->config.src_codeset ); - + hb_deep_log(3, "SRT Start time %"PRId64", stop time %"PRId64, + pv->start_time, pv->stop_time); - if( pv->iconv_context == (iconv_t) -1 ) - { - hb_error("Could not open the iconv library with those file formats\n"); + if (job->pts_to_start != 0) + { + pv->start_time = AV_NOPTS_VALUE; + } - } else { - memset( &pv->current_entry, 0, sizeof( srt_entry_t ) ); + pv->iconv_context = iconv_open( "utf-8", pv->subtitle->config.src_codeset ); + if( pv->iconv_context == (iconv_t) -1 ) + { + hb_error("Could not open the iconv library with those file formats\n"); + goto fail; + } else { + memset( &pv->current_entry, 0, sizeof( srt_entry_t ) ); - pv->file = hb_fopen(w->subtitle->config.src_filename, "r"); + pv->file = hb_fopen(w->subtitle->config.src_filename, "r"); - if( !pv->file ) - { - hb_error("Could not open the SRT subtitle file '%s'\n", - w->subtitle->config.src_filename); - } else { - retval = 0; - } + if( !pv->file ) + { + hb_error("Could not open the SRT subtitle file '%s'\n", + w->subtitle->config.src_filename); + goto fail; } } - if (!retval) + + // Generate generic SSA Script Info. + int height = job->title->geometry.height - job->crop[0] - job->crop[1]; + int width = job->title->geometry.width - job->crop[2] - job->crop[3]; + hb_subtitle_add_ssa_header(w->subtitle, HB_FONT_SANS, + .066 * job->title->geometry.height, + width, height); + return 0; + +fail: + if (pv != NULL) { - // Generate generic SSA Script Info. - int height = job->title->geometry.height - job->crop[0] - job->crop[1]; - int width = job->title->geometry.width - job->crop[2] - job->crop[3]; - hb_subtitle_add_ssa_header(w->subtitle, HB_FONT_SANS, - .066 * job->title->geometry.height, - width, height); + if (pv->iconv_context != (iconv_t) -1) + { + iconv_close(pv->iconv_context); + } + if (pv->file != NULL) + { + fclose(pv->file); + } + free(pv); } - return retval; + return 1; } static int decsrtWork( hb_work_object_t * w, hb_buffer_t ** buf_in, @@ -688,6 +703,21 @@ static int decsrtWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_work_private_t * pv = w->private_data; hb_buffer_t * out = NULL; + if (pv->job->reader_pts_offset == AV_NOPTS_VALUE) + { + // We need to wait for reader to initialize it's pts offset so that + // we know where to start reading SRTs. + *buf_out = NULL; + return HB_WORK_OK; + } + if (pv->start_time == AV_NOPTS_VALUE) + { + pv->start_time = pv->job->reader_pts_offset; + if (pv->job->pts_to_stop > 0) + { + pv->stop_time = pv->job->pts_to_start + pv->job->pts_to_stop; + } + } out = srt_read( pv ); if (out != NULL) { diff --git a/libhb/reader.c b/libhb/reader.c index 71a961a1c..7f1e7cc1a 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -115,7 +115,7 @@ static int hb_reader_open( hb_work_private_t * r ) // to start decoding early using r->pts_to_start hb_bd_seek_pts(r->bd, r->job->pts_to_start); r->duration -= r->job->pts_to_start; - r->job->pts_to_start = 0; + r->job->reader_pts_offset = r->job->pts_to_start; r->start_found = 1; } else @@ -172,6 +172,7 @@ static int hb_reader_open( hb_work_private_t * r ) // first packet we get, subtract that from pts_to_start, and // inspect the reset of the frames in sync. r->duration -= r->job->pts_to_start; + r->job->reader_pts_offset = AV_NOPTS_VALUE; } else { @@ -491,7 +492,8 @@ static int reader_work( hb_work_object_t * w, hb_buffer_t ** buf_in, // libav is allowing SSA subtitles to leak through that are // prior to the seek point. So only make the adjustment to // pts_to_start after we see the next video buffer. - if (buf->s.id != r->job->title->video_id) + if (buf->s.id != r->job->title->video_id || + buf->s.start == AV_NOPTS_VALUE) { hb_buffer_close(&buf); continue; @@ -499,15 +501,7 @@ static int reader_work( hb_work_object_t * w, hb_buffer_t ** buf_in, // We will inspect the timestamps of each frame in sync // to skip from this seek point to the timestamp we // want to start at. - if (buf->s.start != AV_NOPTS_VALUE && - buf->s.start < r->job->pts_to_start) - { - r->job->pts_to_start -= buf->s.start; - } - else if ( buf->s.start >= r->job->pts_to_start ) - { - r->job->pts_to_start = 0; - } + r->job->reader_pts_offset = buf->s.start; r->start_found = 1; } diff --git a/libhb/sync.c b/libhb/sync.c index ac30f7e28..fa56e8d71 100644 --- a/libhb/sync.c +++ b/libhb/sync.c @@ -158,6 +158,7 @@ struct sync_common_s // point-to-point support int start_found; + int64_t pts_to_start; int64_t start_pts; int64_t stop_pts; int wait_for_frame; @@ -1350,7 +1351,7 @@ static void OutputBuffer( sync_common_t * common ) else if (common->wait_for_pts && out_stream->type != SYNC_TYPE_SUBTITLE) { - if (buf->s.start >= common->job->pts_to_start) + if (buf->s.start >= common->pts_to_start) { common->start_found = 1; common->streams[0].frame_count = 0; @@ -1881,6 +1882,20 @@ static void QueueBuffer( sync_stream_t * stream, hb_buffer_t * buf ) } } + // Reader can change job->reader_pts_offset after initialization + // and before we receive the first buffer here. Calculate + // common->pts_to_start here since this is the first opportunity where + // all the necessary information exists. + if (stream->common->pts_to_start == AV_NOPTS_VALUE) + { + hb_job_t * job = stream->common->job; + if (job->pts_to_start > 0) + { + stream->common->pts_to_start = + MAX(0, job->pts_to_start - job->reader_pts_offset); + } + } + // Render offset is only useful for decoders, which are all // upstream of sync. Squash it. buf->s.renderOffset = AV_NOPTS_VALUE; @@ -2242,10 +2257,14 @@ static int syncVideoInit( hb_work_object_t * w, hb_job_t * job) if (job->frame_to_start || job->pts_to_start) { - pv->common->start_found = 0; - pv->common->start_pts = pv->common->job->pts_to_start; + pv->common->start_found = 0; + pv->common->start_pts = job->pts_to_start; pv->common->wait_for_frame = !!job->frame_to_start; pv->common->wait_for_pts = !!job->pts_to_start; + if (job->pts_to_start) + { + pv->common->pts_to_start = AV_NOPTS_VALUE; + } } else { @@ -3048,7 +3067,7 @@ static void UpdateSearchState( sync_common_t * common, int64_t start, if (common->wait_for_frame) p.progress = (float)frame_count / job->frame_to_start; else if (common->wait_for_pts) - p.progress = (float) start / job->pts_to_start; + p.progress = (float) start / common->pts_to_start; else p.progress = 0; if (p.progress > 1.0) @@ -3067,7 +3086,7 @@ static void UpdateSearchState( sync_common_t * common, int64_t start, else if (common->wait_for_pts) { avg = 1000.0 * start / (now - common->st_first); - eta = (job->pts_to_start - start) / avg; + eta = (common->pts_to_start - start) / avg; } p.hours = eta / 3600; p.minutes = (eta % 3600) / 60; diff --git a/libhb/work.c b/libhb/work.c index 1358bc12e..9062111e5 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -1927,6 +1927,13 @@ void hb_work_loop( void * _w ) } } } + else if (w->fifo_in == NULL) + { + // If this work object is a generator (no input fifo) and it + // generated no output, it may be waiting for status from + // another thread. Yield so that we don't spin doing nothing. + hb_yield(); + } } if ( buf_out ) { |