summaryrefslogtreecommitdiffstats
path: root/libhb/reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/reader.c')
-rw-r--r--libhb/reader.c157
1 files changed, 95 insertions, 62 deletions
diff --git a/libhb/reader.c b/libhb/reader.c
index 037fe0931..96d09e96a 100644
--- a/libhb/reader.c
+++ b/libhb/reader.c
@@ -6,6 +6,20 @@
#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 );
+
+hb_work_object_t hb_reader =
+{
+ WORK_READER,
+ "Reader",
+ hb_reader_init,
+ NULL,
+ hb_reader_close,
+ NULL,
+ NULL
+};
+
typedef struct
{
double average; // average time between packets
@@ -15,7 +29,7 @@ typedef struct
int valid; // Stream timing is not valid until next scr.
} stream_timing_t;
-typedef struct
+struct hb_work_private_s
{
hb_job_t * job;
hb_title_t * title;
@@ -37,25 +51,51 @@ typedef struct
int start_found; // found pts_to_start point
int64_t pts_to_start;
uint64_t st_first;
-} hb_reader_t;
+};
/***********************************************************************
* Local prototypes
**********************************************************************/
-static void ReaderFunc( void * );
static hb_fifo_t ** GetFifoForId( hb_job_t * job, int id );
-static void UpdateState( hb_reader_t * r, int64_t start);
+static void UpdateState( hb_work_private_t * r, int64_t start);
/***********************************************************************
* hb_reader_init
***********************************************************************
*
**********************************************************************/
-hb_thread_t * hb_reader_init( hb_job_t * job )
+static int hb_reader_open( hb_work_private_t * r )
{
- hb_reader_t * r;
+ if ( r->title->type == HB_BD_TYPE )
+ {
+ if ( !( r->bd = hb_bd_init( r->title->path ) ) )
+ return 1;
+ }
+ else if ( r->title->type == HB_DVD_TYPE )
+ {
+ if ( !( r->dvd = hb_dvd_init( r->title->path ) ) )
+ return 1;
+ }
+ else if ( r->title->type == HB_STREAM_TYPE ||
+ r->title->type == HB_FF_STREAM_TYPE )
+ {
+ if ( !( r->stream = hb_stream_open( r->title->path, r->title, 0 ) ) )
+ return 1;
+ }
+ else
+ {
+ // Unknown type, should never happen
+ return 1;
+ }
+ return 0;
+}
- r = calloc( sizeof( hb_reader_t ), 1 );
+static int hb_reader_init( hb_work_object_t * w, hb_job_t * job )
+{
+ hb_work_private_t * r;
+
+ r = calloc( sizeof( hb_work_private_t ), 1 );
+ w->private_data = r;
r->job = job;
r->title = job->title;
@@ -81,11 +121,47 @@ hb_thread_t * hb_reader_init( hb_job_t * job )
r->pts_to_start = MAX(0, job->pts_to_start - 180000);
}
- return hb_thread_init( "reader", ReaderFunc, r,
- HB_NORMAL_PRIORITY );
+ // The stream needs to be open before starting the reader thead
+ // to prevent a race with decoders that may share information
+ // with the reader. Specifically avcodec needs this.
+ if ( hb_reader_open( r ) )
+ {
+ free( r->stream_timing );
+ free( r );
+ return 1;
+ }
+ return 0;
+}
+
+
+static void hb_reader_close( hb_work_object_t * w )
+{
+ hb_work_private_t * r = w->private_data;
+
+ if (r->bd)
+ {
+ hb_bd_stop( r->bd );
+ hb_bd_close( &r->bd );
+ }
+ else if (r->dvd)
+ {
+ hb_dvd_stop( r->dvd );
+ hb_dvd_close( &r->dvd );
+ }
+ else if (r->stream)
+ {
+ hb_stream_close(&r->stream);
+ }
+
+ if ( r->stream_timing )
+ {
+ free( r->stream_timing );
+ }
+
+ free( r );
}
-static void push_buf( const hb_reader_t *r, hb_fifo_t *fifo, hb_buffer_t *buf )
+static void push_buf( const hb_work_private_t *r, hb_fifo_t *fifo, hb_buffer_t *buf )
{
while ( !*r->die && !r->job->done )
{
@@ -102,7 +178,7 @@ static void push_buf( const hb_reader_t *r, hb_fifo_t *fifo, hb_buffer_t *buf )
}
}
-static int is_audio( hb_reader_t *r, int id )
+static int is_audio( hb_work_private_t *r, int id )
{
int i;
hb_audio_t *audio;
@@ -127,7 +203,7 @@ static int is_audio( hb_reader_t *r, int id )
// find the per-stream timing state for 'buf'
-static stream_timing_t *find_st( hb_reader_t *r, const hb_buffer_t *buf )
+static stream_timing_t *find_st( hb_work_private_t *r, const hb_buffer_t *buf )
{
stream_timing_t *st = r->stream_timing;
for ( ; st->id != -1; ++st )
@@ -140,7 +216,7 @@ static stream_timing_t *find_st( hb_reader_t *r, const hb_buffer_t *buf )
// find or create the per-stream timing state for 'buf'
-static stream_timing_t *id_to_st( hb_reader_t *r, const hb_buffer_t *buf, int valid )
+static stream_timing_t *id_to_st( hb_work_private_t *r, const hb_buffer_t *buf, int valid )
{
stream_timing_t *st = r->stream_timing;
while ( st->id != buf->id && st->id != -1)
@@ -177,7 +253,7 @@ static stream_timing_t *id_to_st( hb_reader_t *r, const hb_buffer_t *buf, int va
// update the average inter-packet time of the stream associated with 'buf'
// using a recursive low-pass filter with a 16 packet time constant.
-static void update_ipt( hb_reader_t *r, const hb_buffer_t *buf )
+static void update_ipt( hb_work_private_t *r, const hb_buffer_t *buf )
{
stream_timing_t *st = id_to_st( r, buf, 1 );
double dt = buf->renderOffset - st->last;
@@ -194,7 +270,7 @@ static void update_ipt( hb_reader_t *r, const hb_buffer_t *buf )
// such that 'buf' will follow the previous packet of this stream separated
// by the average packet time of the stream.
-static void new_scr_offset( hb_reader_t *r, hb_buffer_t *buf )
+static void new_scr_offset( hb_work_private_t *r, hb_buffer_t *buf )
{
stream_timing_t *st = id_to_st( r, buf, 1 );
int64_t last;
@@ -224,9 +300,10 @@ static void new_scr_offset( hb_reader_t *r, hb_buffer_t *buf )
***********************************************************************
*
**********************************************************************/
-static void ReaderFunc( void * _r )
+void ReadLoop( void * _w )
{
- hb_reader_t * r = _r;
+ hb_work_object_t * w = _w;
+ hb_work_private_t * r = w->private_data;
hb_fifo_t ** fifos;
hb_buffer_t * buf;
hb_list_t * list;
@@ -234,28 +311,6 @@ static void ReaderFunc( void * _r )
int chapter = -1;
int chapter_end = r->job->chapter_end;
- if ( r->title->type == HB_BD_TYPE )
- {
- if ( !( r->bd = hb_bd_init( r->title->path ) ) )
- return;
- }
- else if ( r->title->type == HB_DVD_TYPE )
- {
- if ( !( r->dvd = hb_dvd_init( r->title->path ) ) )
- return;
- }
- else if ( r->title->type == HB_STREAM_TYPE ||
- r->title->type == HB_FF_STREAM_TYPE )
- {
- if ( !( r->stream = hb_stream_open( r->title->path, r->title ) ) )
- return;
- }
- else
- {
- // Unknown type, should never happen
- return;
- }
-
if (r->bd)
{
if( !hb_bd_start( r->bd, r->title ) )
@@ -601,37 +656,15 @@ static void ReaderFunc( void * _r )
}
hb_list_empty( &list );
- if (r->bd)
- {
- hb_bd_stop( r->bd );
- hb_bd_close( &r->bd );
- }
- else if (r->dvd)
- {
- hb_dvd_stop( r->dvd );
- hb_dvd_close( &r->dvd );
- }
- else if (r->stream)
- {
- hb_stream_close(&r->stream);
- }
-
- if ( r->stream_timing )
- {
- free( r->stream_timing );
- }
hb_log( "reader: done. %d scr changes", r->demux.scr_changes );
if ( r->demux.dts_drops )
{
hb_log( "reader: %d drops because DTS out of range", r->demux.dts_drops );
}
-
- free( r );
- _r = NULL;
}
-static void UpdateState( hb_reader_t * r, int64_t start)
+static void UpdateState( hb_work_private_t * r, int64_t start)
{
hb_state_t state;
uint64_t now;