summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2017-04-15 13:20:21 -0600
committerJohn Stebbins <[email protected]>2017-04-15 13:22:55 -0600
commitbb92ab00e37bdb87b528b1901d956c1f24417387 (patch)
treef327eb191c83b6ffad38ad32c8d144f6b0582ee5 /libhb
parent52d4c21b22cfc91b63a680aa7e475cc0ca6012cb (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.h4
-rw-r--r--libhb/decsrtsub.c150
-rw-r--r--libhb/reader.c16
-rw-r--r--libhb/sync.c29
-rw-r--r--libhb/work.c7
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 )
{