summaryrefslogtreecommitdiffstats
path: root/libhb/reader.c
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2015-11-03 09:46:28 -0800
committerJohn Stebbins <[email protected]>2015-11-09 11:06:59 -0800
commita986f54a4109bb8c3b2fb57849b4b0ea01e3c522 (patch)
tree7add9d007dc8bdd72114637c8f3f7361621ad4a5 /libhb/reader.c
parent63b340ebc33d57aeda22e340dab48b1df2106541 (diff)
libhb: make muxer, sync, and reader behave like other work objects
simplify job initialization sequence, clean up code, and document dependencies in the sequence better. Make hb_add set job->sequence_id. It is no longer necessary for the frontend to do this. If the frontend needs the sequence_id, it is returned by hb_add(). Clean up use of interjob. do_job() now uses sequence_id to detect when a new sequence of related jobs is running and automatically clears interjob.
Diffstat (limited to 'libhb/reader.c')
-rw-r--r--libhb/reader.c657
1 files changed, 315 insertions, 342 deletions
diff --git a/libhb/reader.c b/libhb/reader.c
index dda2a2e71..0c6f6d853 100644
--- a/libhb/reader.c
+++ b/libhb/reader.c
@@ -8,18 +8,21 @@
*/
#include "hb.h"
-static int hb_reader_init( hb_work_object_t * w, hb_job_t * job );
-static void hb_reader_close( hb_work_object_t * w );
+static int reader_init( hb_work_object_t * w, hb_job_t * job );
+static void reader_close( hb_work_object_t * w );
+static int reader_work( hb_work_object_t * w, hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out);
hb_work_object_t hb_reader =
{
- WORK_READER,
- "Reader",
- hb_reader_init,
- NULL,
- hb_reader_close,
- NULL,
- NULL
+ .id = WORK_READER,
+ .name = "Reader",
+ .init = reader_init,
+ .work = reader_work,
+ .close = reader_close,
+ .info = NULL,
+ .bsinfo = NULL,
+ .flush = NULL
};
typedef struct
@@ -56,6 +59,7 @@ struct hb_work_private_s
int start_found; // found pts_to_start point
int64_t pts_to_start;
+ int chapter_end;
uint64_t st_first;
uint64_t duration;
hb_fifo_t * fifos[100];
@@ -68,7 +72,7 @@ static hb_fifo_t ** GetFifoForId( hb_work_private_t * r, int id );
static void UpdateState( hb_work_private_t * r, int64_t start);
/***********************************************************************
- * hb_reader_init
+ * reader_init
***********************************************************************
*
**********************************************************************/
@@ -78,27 +82,114 @@ static int hb_reader_open( hb_work_private_t * r )
{
if ( !( r->bd = hb_bd_init( r->h, r->title->path ) ) )
return 1;
+ if(!hb_bd_start(r->bd, r->title))
+ {
+ hb_bd_close(&r->bd);
+ return 1;
+ }
+ if (r->job->start_at_preview)
+ {
+ // XXX code from DecodePreviews - should go into its own routine
+ hb_bd_seek(r->bd, (float)r->job->start_at_preview /
+ (r->job->seek_points ? (r->job->seek_points + 1.0)
+ : 11.0));
+ }
+ else if (r->job->pts_to_start)
+ {
+ // Note, bd seeks always put us to an i-frame. no need
+ // 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->start_found = 1;
+ }
+ else
+ {
+ hb_bd_seek_chapter(r->bd, r->job->chapter_start);
+ }
+ if (r->job->angle > 1)
+ {
+ hb_bd_set_angle(r->bd, r->job->angle - 1);
+ }
}
- else if ( r->title->type == HB_DVD_TYPE )
+ else if (r->title->type == HB_DVD_TYPE)
{
if ( !( r->dvd = hb_dvd_init( r->h, r->title->path ) ) )
return 1;
+ if(!hb_dvd_start( r->dvd, r->title, r->job->chapter_start))
+ {
+ hb_dvd_close(&r->dvd);
+ return 1;
+ }
+ if (r->job->angle)
+ {
+ hb_dvd_set_angle(r->dvd, r->job->angle);
+ }
+
+ if (r->job->start_at_preview)
+ {
+ hb_dvd_seek(r->dvd, (float)r->job->start_at_preview /
+ (r->job->seek_points ? (r->job->seek_points + 1.0)
+ : 11.0));
+ }
}
- else if ( r->title->type == HB_STREAM_TYPE ||
- r->title->type == HB_FF_STREAM_TYPE )
+ else if (r->title->type == HB_STREAM_TYPE ||
+ r->title->type == HB_FF_STREAM_TYPE)
{
if (!(r->stream = hb_stream_open(r->h, r->title->path, r->title, 0)))
return 1;
+ if (r->job->start_at_preview)
+ {
+ hb_stream_seek(r->stream, (float)(r->job->start_at_preview - 1) /
+ (r->job->seek_points ? (r->job->seek_points + 1.0)
+ : 11.0));
+ }
+ else if (r->job->pts_to_start)
+ {
+ if (hb_stream_seek_ts( r->stream, r->job->pts_to_start ) >= 0)
+ {
+ // Seek takes us to the nearest I-frame before the timestamp
+ // that we want. So we will retrieve the start time of the
+ // first packet we get, subtract that from pts_to_start, and
+ // inspect the reset of the frames in sync.
+ r->start_found = 2;
+ r->duration -= r->job->pts_to_start;
+ }
+ // hb_stream_seek_ts does nothing for TS streams and will return
+ // an error.
+ }
+ else
+ {
+ //
+ // Standard stream, seek to the starting chapter, if set,
+ // and track the end chapter so that we end at the right time.
+ hb_chapter_t *chap;
+ int start = r->job->chapter_start;
+ chap = hb_list_item(r->job->list_chapter, r->job->chapter_end - 1);
+
+ r->chapter_end = chap->index;
+ if (start > 1)
+ {
+ chap = hb_list_item(r->job->list_chapter, start - 1);
+ start = chap->index;
+ }
+
+ /*
+ * Seek to the start chapter.
+ */
+ hb_stream_seek_chapter(r->stream, start);
+ }
}
else
{
// Unknown type, should never happen
return 1;
}
+
return 0;
}
-static int hb_reader_init( hb_work_object_t * w, hb_job_t * job )
+static int reader_init( hb_work_object_t * w, hb_job_t * job )
{
hb_work_private_t * r;
@@ -124,6 +215,7 @@ static int hb_reader_init( hb_work_object_t * w, hb_job_t * job )
r->demux.last_scr = AV_NOPTS_VALUE;
+ r->chapter_end = job->chapter_end;
if ( !job->pts_to_start )
r->start_found = 1;
else
@@ -171,7 +263,7 @@ static int hb_reader_init( hb_work_object_t * w, hb_job_t * job )
}
-static void hb_reader_close( hb_work_object_t * w )
+static void reader_close( hb_work_object_t * w )
{
hb_work_private_t * r = w->private_data;
@@ -359,401 +451,282 @@ static void new_scr_offset( hb_work_private_t *r, hb_buffer_t *buf )
r->scr_changes = r->demux.scr_changes;
}
-/***********************************************************************
- * ReaderFunc
- ***********************************************************************
- *
- **********************************************************************/
-void ReadLoop( void * _w )
+static void reader_send_eof( hb_work_private_t * r )
+{
+ int ii;
+
+ // send eof buffers downstream to decoders to signal we're done.
+ push_buf(r, r->job->fifo_mpeg2, hb_buffer_eof_init());
+
+ hb_audio_t *audio;
+ for (ii = 0; (audio = hb_list_item(r->job->list_audio, ii)); ++ii)
+ {
+ if (audio->priv.fifo_in)
+ push_buf(r, audio->priv.fifo_in, hb_buffer_eof_init());
+ }
+
+ hb_subtitle_t *subtitle;
+ for (ii = 0; (subtitle = hb_list_item(r->job->list_subtitle, ii)); ++ii)
+ {
+ if (subtitle->fifo_in && subtitle->source != SRTSUB)
+ push_buf(r, subtitle->fifo_in, hb_buffer_eof_init());
+ }
+ hb_log("reader: done. %d scr changes", r->demux.scr_changes);
+}
+
+static int reader_work( hb_work_object_t * w, hb_buffer_t ** buf_in,
+ hb_buffer_t ** buf_out)
{
- hb_work_object_t * w = _w;
hb_work_private_t * r = w->private_data;
hb_fifo_t ** fifos;
- hb_buffer_t * buf = NULL;
+ hb_buffer_t * buf;
hb_buffer_list_t list;
- int n;
- int chapter = -1;
- int chapter_end = r->job->chapter_end;
- uint8_t done = 0;
+ int ii, chapter = -1;
+
+ hb_buffer_list_clear(&list);
if (r->bd)
+ chapter = hb_bd_chapter( r->bd );
+ else if (r->dvd)
+ chapter = hb_dvd_chapter( r->dvd );
+ else if (r->stream)
+ chapter = hb_stream_chapter( r->stream );
+
+ if( chapter < 0 )
{
- if( !hb_bd_start( r->bd, r->title ) )
- {
- hb_bd_close( &r->bd );
- return;
- }
- if ( r->job->start_at_preview )
- {
- // XXX code from DecodePreviews - should go into its own routine
- hb_bd_seek( r->bd, (float)r->job->start_at_preview /
- ( r->job->seek_points ? ( r->job->seek_points + 1.0 ) : 11.0 ) );
- }
- else if ( r->job->pts_to_start )
- {
- // Note, bd seeks always put us to an i-frame. no need
- // 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->start_found = 1;
- }
- else
- {
- hb_bd_seek_chapter( r->bd, r->job->chapter_start );
- }
- if (r->job->angle > 1)
- {
- hb_bd_set_angle( r->bd, r->job->angle - 1 );
- }
+ hb_log( "reader: end of the title reached" );
+ reader_send_eof(r);
+ return HB_WORK_DONE;
}
- else if (r->dvd)
+ if( chapter > r->chapter_end )
{
- /*
- * XXX this code is a temporary hack that should go away if/when
- * chapter merging goes away in libhb/dvd.c
- * map the start and end chapter numbers to on-media chapter
- * numbers since chapter merging could cause the handbrake numbers
- * to diverge from the media numbers and, if our chapter_end is after
- * a media chapter that got merged, we'll stop ripping too early.
- */
- int start = r->job->chapter_start;
- hb_chapter_t *chap = hb_list_item( r->job->list_chapter, chapter_end - 1 );
-
- chapter_end = chap->index;
- if (start > 1)
- {
- chap = hb_list_item( r->job->list_chapter, start - 1 );
- start = chap->index;
- }
- /* end chapter mapping XXX */
-
- if( !hb_dvd_start( r->dvd, r->title, start ) )
- {
- hb_dvd_close( &r->dvd );
- return;
- }
- if (r->job->angle)
- {
- hb_dvd_set_angle( r->dvd, r->job->angle );
- }
+ hb_log("reader: end of chapter %d (media %d) reached at media chapter %d",
+ r->job->chapter_end, r->chapter_end, chapter);
+ reader_send_eof(r);
+ return HB_WORK_DONE;
+ }
- if ( r->job->start_at_preview )
+ if (r->bd)
+ {
+ if( (buf = hb_bd_read( r->bd )) == NULL )
{
- // XXX code from DecodePreviews - should go into its own routine
- hb_dvd_seek( r->dvd, (float)r->job->start_at_preview /
- ( r->job->seek_points ? ( r->job->seek_points + 1.0 ) : 11.0 ) );
+ reader_send_eof(r);
+ return HB_WORK_DONE;
}
}
- else if ( r->stream && r->job->start_at_preview )
- {
-
- // XXX code from DecodePreviews - should go into its own routine
- hb_stream_seek( r->stream, (float)( r->job->start_at_preview - 1 ) /
- ( r->job->seek_points ? ( r->job->seek_points + 1.0 ) : 11.0 ) );
-
- }
- else if ( r->stream && r->job->pts_to_start )
+ else if (r->dvd)
{
- if ( hb_stream_seek_ts( r->stream, r->job->pts_to_start ) >= 0 )
+ if( (buf = hb_dvd_read( r->dvd )) == NULL )
{
- // Seek takes us to the nearest I-frame before the timestamp
- // that we want. So we will retrieve the start time of the
- // first packet we get, subtract that from pts_to_start, and
- // inspect the reset of the frames in sync.
- r->start_found = 2;
- r->duration -= r->job->pts_to_start;
+ reader_send_eof(r);
+ return HB_WORK_DONE;
}
- // hb_stream_seek_ts does nothing for TS streams and will return
- // an error.
- }
- else if( r->stream )
+ }
+ else if (r->stream)
{
- /*
- * Standard stream, seek to the starting chapter, if set, and track the
- * end chapter so that we end at the right time.
- */
- int start = r->job->chapter_start;
- hb_chapter_t *chap = hb_list_item( r->job->list_chapter, chapter_end - 1 );
-
- chapter_end = chap->index;
- if (start > 1)
+ if ( (buf = hb_stream_read( r->stream )) == NULL )
{
- chap = hb_list_item( r->job->list_chapter, start - 1 );
- start = chap->index;
+ reader_send_eof(r);
+ return HB_WORK_DONE;
}
-
- /*
- * Seek to the start chapter.
- */
- hb_stream_seek_chapter( r->stream, start );
}
- hb_buffer_list_clear(&list);
+ (hb_demux[r->title->demuxer])(buf, &list, &r->demux);
- while(!*r->die && !r->job->done && !done)
+ while ((buf = hb_buffer_list_rem_head(&list)) != NULL)
{
- if (r->bd)
- chapter = hb_bd_chapter( r->bd );
- else if (r->dvd)
- chapter = hb_dvd_chapter( r->dvd );
- else if (r->stream)
- chapter = hb_stream_chapter( r->stream );
+ fifos = GetFifoForId( r, buf->s.id );
- if( chapter < 0 )
+ if (fifos && r->stream && r->start_found == 2 )
{
- hb_log( "reader: end of the title reached" );
- break;
- }
- if( chapter > chapter_end )
- {
- hb_log( "reader: end of chapter %d (media %d) reached at media chapter %d",
- r->job->chapter_end, chapter_end, chapter );
- break;
- }
-
- if (buf == NULL)
- {
- if (r->bd)
+ // 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)
{
- if( (buf = hb_bd_read( r->bd )) == NULL )
- {
- break;
- }
- }
- else if (r->dvd)
- {
- if( (buf = hb_dvd_read( r->dvd )) == NULL )
- {
- break;
- }
+ r->job->pts_to_start -= buf->s.start;
}
- else if (r->stream)
+ else if ( buf->s.start >= r->job->pts_to_start )
{
- if ( (buf = hb_stream_read( r->stream )) == NULL )
- {
- break;
- }
+ r->job->pts_to_start = 0;
}
+ r->start_found = 1;
}
- (hb_demux[r->title->demuxer])(buf, &list, &r->demux);
-
- while ((buf = hb_buffer_list_rem_head(&list)) != NULL)
+ if ( fifos && ! r->saw_video && !r->job->indepth_scan )
{
- fifos = GetFifoForId( r, buf->s.id );
-
- if (fifos && r->stream && r->start_found == 2 )
+ // The first data packet with a PTS from an audio or video stream
+ // that we're decoding defines 'time zero'. Discard packets until
+ // we get one.
+ if (buf->s.start != AV_NOPTS_VALUE &&
+ buf->s.renderOffset != AV_NOPTS_VALUE &&
+ (buf->s.id == r->title->video_id ||
+ is_audio( r, buf->s.id)))
{
- // 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->start_found = 1;
+ // force a new scr offset computation
+ r->scr_changes = r->demux.scr_changes - 1;
+ // create a stream state if we don't have one so the
+ // offset will get computed correctly.
+ id_to_st( r, buf, 1 );
+ r->saw_video = 1;
+ hb_log( "reader: first SCR %"PRId64" id 0x%x DTS %"PRId64,
+ r->demux.last_scr, buf->s.id, buf->s.renderOffset );
}
-
- if ( fifos && ! r->saw_video && !r->job->indepth_scan )
+ else
{
- // The first data packet with a PTS from an audio or video stream
- // that we're decoding defines 'time zero'. Discard packets until
- // we get one.
- if (buf->s.start != AV_NOPTS_VALUE &&
- buf->s.renderOffset != AV_NOPTS_VALUE &&
- (buf->s.id == r->title->video_id ||
- is_audio( r, buf->s.id)))
- {
- // force a new scr offset computation
- r->scr_changes = r->demux.scr_changes - 1;
- // create a stream state if we don't have one so the
- // offset will get computed correctly.
- id_to_st( r, buf, 1 );
- r->saw_video = 1;
- hb_log( "reader: first SCR %"PRId64" id 0x%x DTS %"PRId64,
- r->demux.last_scr, buf->s.id, buf->s.renderOffset );
- }
- else
- {
- fifos = NULL;
- }
+ fifos = NULL;
}
+ }
- if ( r->job->indepth_scan || fifos )
+ if ( r->job->indepth_scan || fifos )
+ {
+ if ( buf->s.renderOffset != AV_NOPTS_VALUE )
{
- if ( buf->s.renderOffset != AV_NOPTS_VALUE )
+ if ( r->scr_changes != r->demux.scr_changes )
{
- if ( r->scr_changes != r->demux.scr_changes )
+ // This is the first audio or video packet after an SCR
+ // change. Compute a new scr offset that would make this
+ // packet follow the last of this stream with the
+ // correct average spacing.
+ stream_timing_t *st = id_to_st( r, buf, 0 );
+
+ // if this is the video stream and we don't have
+ // audio yet or this is an audio stream
+ // generate a new scr
+ if ( st->is_audio ||
+ ( st == r->stream_timing && !r->saw_audio ) )
{
- // This is the first audio or video packet after an SCR
- // change. Compute a new scr offset that would make this
- // packet follow the last of this stream with the
- // correct average spacing.
- stream_timing_t *st = id_to_st( r, buf, 0 );
-
- // if this is the video stream and we don't have
- // audio yet or this is an audio stream
- // generate a new scr
- if ( st->is_audio ||
- ( st == r->stream_timing && !r->saw_audio ) )
+ new_scr_offset( r, buf );
+ r->sub_scr_set = 0;
+ }
+ else
+ {
+ // defer the scr change until we get some
+ // audio since audio has a timestamp per
+ // frame but video & subtitles don't. Clear
+ // the timestamps so the decoder will generate
+ // them from the frame durations.
+ if (is_subtitle(r, buf->s.id) &&
+ buf->s.start != AV_NOPTS_VALUE)
{
- new_scr_offset( r, buf );
- r->sub_scr_set = 0;
+ if (!r->sub_scr_set)
+ {
+ // We can't generate timestamps in the
+ // subtitle decoder as we can for
+ // audio & video. So we need to make
+ // the closest guess that we can
+ // for the subtitles start time here.
+ int64_t last = r->stream_timing[0].last;
+ r->scr_offset = buf->s.start - last;
+ r->sub_scr_set = 1;
+ }
}
else
{
- // defer the scr change until we get some
- // audio since audio has a timestamp per
- // frame but video & subtitles don't. Clear
- // the timestamps so the decoder will generate
- // them from the frame durations.
- if (is_subtitle(r, buf->s.id) &&
- buf->s.start != AV_NOPTS_VALUE)
- {
- if (!r->sub_scr_set)
- {
- // We can't generate timestamps in the
- // subtitle decoder as we can for
- // audio & video. So we need to make
- // the closest guess that we can
- // for the subtitles start time here.
- int64_t last = r->stream_timing[0].last;
- r->scr_offset = buf->s.start - last;
- r->sub_scr_set = 1;
- }
- }
- else
- {
- buf->s.start = AV_NOPTS_VALUE;
- buf->s.renderOffset = AV_NOPTS_VALUE;
- }
+ buf->s.start = AV_NOPTS_VALUE;
+ buf->s.renderOffset = AV_NOPTS_VALUE;
}
}
}
- if ( buf->s.start != AV_NOPTS_VALUE )
- {
- int64_t start = buf->s.start - r->scr_offset;
+ }
+ if ( buf->s.start != AV_NOPTS_VALUE )
+ {
+ int64_t start = buf->s.start - r->scr_offset;
- if (!r->start_found || r->job->indepth_scan)
- {
- UpdateState( r, start );
- }
+ if (!r->start_found || r->job->indepth_scan)
+ {
+ UpdateState( r, start );
+ }
- if (r->job->indepth_scan && r->job->pts_to_stop &&
- start >= r->pts_to_start + r->job->pts_to_stop)
- {
- // sync normally would terminate p-to-p
- // but sync doesn't run during indepth scan
- hb_log( "reader: reached pts %"PRId64", exiting early", start );
- done = 1;
- break;
- }
+ if (r->job->indepth_scan && r->job->pts_to_stop &&
+ start >= r->pts_to_start + r->job->pts_to_stop)
+ {
+ // sync normally would terminate p-to-p
+ // but sync doesn't run during indepth scan
+ hb_log("reader: reached pts %"PRId64", exiting early", start);
+ reader_send_eof(r);
+ hb_buffer_list_close(&list);
+ return HB_WORK_DONE;
+ }
- if (!r->start_found && start >= r->pts_to_start)
- {
- // pts_to_start point found
- r->start_found = 1;
- if (r->stream)
- {
- // libav multi-threaded decoders can get into
- // a bad state if the initial data is not
- // decodable. So try to improve the chances of
- // a good start by waiting for an initial iframe
- hb_stream_set_need_keyframe(r->stream, 1);
- hb_buffer_close( &buf );
- continue;
- }
- }
- // This log is handy when you need to debug timing problems
- //hb_log("id %x scr_offset %"PRId64
- // " start %"PRId64" --> %"PRId64"",
- // buf->s.id, r->scr_offset, buf->s.start,
- // buf->s.start - r->scr_offset);
- buf->s.start -= r->scr_offset;
- if ( buf->s.stop != AV_NOPTS_VALUE )
+ if (!r->start_found && start >= r->pts_to_start)
+ {
+ // pts_to_start point found
+ r->start_found = 1;
+ if (r->stream)
{
- buf->s.stop -= r->scr_offset;
+ // libav multi-threaded decoders can get into
+ // a bad state if the initial data is not
+ // decodable. So try to improve the chances of
+ // a good start by waiting for an initial iframe
+ hb_stream_set_need_keyframe(r->stream, 1);
+ hb_buffer_close( &buf );
+ continue;
}
}
- if ( buf->s.renderOffset != AV_NOPTS_VALUE )
+ // This log is handy when you need to debug timing problems
+ //hb_log("id %x scr_offset %"PRId64
+ // " start %"PRId64" --> %"PRId64"",
+ // buf->s.id, r->scr_offset, buf->s.start,
+ // buf->s.start - r->scr_offset);
+ buf->s.start -= r->scr_offset;
+ if ( buf->s.stop != AV_NOPTS_VALUE )
{
- // This packet is referenced to the same SCR as the last.
- // Adjust timestamp to remove the System Clock Reference
- // offset then update the average inter-packet time
- // for this stream.
- buf->s.renderOffset -= r->scr_offset;
- update_ipt( r, buf );
+ buf->s.stop -= r->scr_offset;
}
-#if 0
- // JAS: This was added to fix a rare "audio time went backward"
- // sync error I found in one sample. But it has a bad side
- // effect on DVDs, causing frequent "adding silence" sync
- // errors. So I am disabling it.
- else
- {
- update_ipt( r, buf );
- }
-#endif
}
- if( fifos )
+ if ( buf->s.renderOffset != AV_NOPTS_VALUE )
{
- if ( !r->start_found )
- {
- hb_buffer_close( &buf );
- continue;
- }
-
- buf->sequence = r->sequence++;
- /* if there are mutiple output fifos, send a copy of the
- * buffer down all but the first (we have to not ship the
- * original buffer or we'll race with the thread that's
- * consuming the buffer & inject garbage into the data stream). */
- for( n = 1; fifos[n] != NULL; n++)
- {
- hb_buffer_t *buf_copy = hb_buffer_init( buf->size );
- buf_copy->s = buf->s;
- memcpy( buf_copy->data, buf->data, buf->size );
- push_buf( r, fifos[n], buf_copy );
- }
- push_buf( r, fifos[0], buf );
- buf = NULL;
+ // This packet is referenced to the same SCR as the last.
+ // Adjust timestamp to remove the System Clock Reference
+ // offset then update the average inter-packet time
+ // for this stream.
+ buf->s.renderOffset -= r->scr_offset;
+ update_ipt( r, buf );
}
+#if 0
+ // JAS: This was added to fix a rare "audio time went backward"
+ // sync error I found in one sample. But it has a bad side
+ // effect on DVDs, causing frequent "adding silence" sync
+ // errors. So I am disabling it.
else
{
- hb_buffer_close( &buf );
+ update_ipt( r, buf );
}
+#endif
}
- }
-
- // send empty buffers downstream to video & audio decoders to signal we're done.
- if( !*r->die && !r->job->done )
- {
- push_buf(r, r->job->fifo_mpeg2, hb_buffer_eof_init());
-
- hb_audio_t *audio;
- for( n = 0; (audio = hb_list_item( r->job->list_audio, n)); ++n )
+ if( fifos )
{
- if ( audio->priv.fifo_in )
- push_buf(r, audio->priv.fifo_in, hb_buffer_eof_init());
- }
+ if ( !r->start_found )
+ {
+ hb_buffer_close( &buf );
+ continue;
+ }
- hb_subtitle_t *subtitle;
- for( n = 0; (subtitle = hb_list_item( r->job->list_subtitle, n)); ++n )
+ buf->sequence = r->sequence++;
+ /* if there are mutiple output fifos, send a copy of the
+ * buffer down all but the first (we have to not ship the
+ * original buffer or we'll race with the thread that's
+ * consuming the buffer & inject garbage into the data stream). */
+ for (ii = 1; fifos[ii] != NULL; ii++)
+ {
+ hb_buffer_t *buf_copy = hb_buffer_init(buf->size);
+ buf_copy->s = buf->s;
+ memcpy(buf_copy->data, buf->data, buf->size);
+ push_buf(r, fifos[ii], buf_copy);
+ }
+ push_buf(r, fifos[0], buf);
+ buf = NULL;
+ }
+ else
{
- if ( subtitle->fifo_in && subtitle->source == VOBSUB)
- push_buf(r, subtitle->fifo_in, hb_buffer_eof_init());
+ hb_buffer_close(&buf);
}
}
hb_buffer_list_close(&list);
-
- hb_log( "reader: done. %d scr changes", r->demux.scr_changes );
+ return HB_WORK_OK;
}
static void UpdateState( hb_work_private_t * r, int64_t start)
@@ -859,7 +832,7 @@ static hb_fifo_t ** GetFifoForId( hb_work_private_t * r, int id )
{
return r->fifos;
}
-
+
if( !job->indepth_scan )
{
for( i = n = 0; i < hb_list_count( job->list_audio ); i++ )