OSDN Git Service

Fix two of my stupid bugs that prevented using the queue with transport streams:
authorvan <van@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Thu, 20 Mar 2008 05:28:36 +0000 (05:28 +0000)
committervan <van@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Thu, 20 Mar 2008 05:28:36 +0000 (05:28 +0000)
 - keep a cache of the pid/substream id mappings from each scan rather than assuming an encode will immediately follow a scan (there will be lots of scans followed by lots of encodes when the queue is used).
 - rewrite a few things to get rid of static variables. hb_ts_stream_decode is called by both scan & reader and they're in different threads. All the working storage & state has to either be in the stream struct or on the stack so it's private to the calling thread or it gets corrupted when doing a scan in the middle of an encode.

git-svn-id: svn://localhost/HandBrake/trunk@1351 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/internal.h
libhb/reader.c
libhb/scan.c
libhb/stream.c

index a2b4799..8095967 100644 (file)
@@ -136,7 +136,7 @@ int          hb_dvd_chapter( hb_dvd_t * );
 int          hb_dvd_is_break( hb_dvd_t * d );
 void         hb_dvd_close( hb_dvd_t ** );
 
-hb_stream_t * hb_stream_open( char * path );
+hb_stream_t * hb_stream_open( char * path, int opentype );
 void            hb_stream_close( hb_stream_t ** );
 hb_title_t * hb_stream_title_scan( hb_stream_t *);
 int          hb_stream_read( hb_stream_t *, hb_buffer_t *);
index b2bff03..db1c7af 100644 (file)
@@ -68,7 +68,7 @@ static void ReaderFunc( void * _r )
 
     if( !( r->dvd = hb_dvd_init( r->title->dvd ) ) )
     {
-        if ( !(r->stream = hb_stream_open(r->title->dvd) ) )
+        if ( !( r->stream = hb_stream_open( r->title->dvd, 1 ) ) )
         {
           return;
         }
@@ -212,7 +212,7 @@ static void ReaderFunc( void * _r )
                  * new packet lines up with that of the previous packet.
                  */
                 int64_t scr_delta = buf->stop - r->last_scr;
-                if ( scr_delta > 67500 || scr_delta < -900 )
+                if ( scr_delta > (90*700) || scr_delta < -90 )
                 {
                     ++r->scr_changes;
                     r->scr_offset += scr_delta - 1;
index e3972a6..5b62fec 100644 (file)
@@ -70,7 +70,7 @@ static void ScanFunc( void * _data )
             }
         }
     }
-    else if ( (data->stream = hb_stream_open (data->path)) != NULL )
+    else if ( (data->stream = hb_stream_open( data->path, 0 ) ) != NULL )
     {
         hb_list_add( data->list_title, hb_stream_title_scan( data->stream ) );
     }
index 9b6fd43..e376c69 100755 (executable)
 
 #define min(a, b) a < b ? a : b
 
-typedef enum { hb_stream_type_unknown = 0, hb_stream_type_transport, hb_stream_type_program } hb_stream_type_t;
+typedef enum {
+    hb_stream_type_unknown = 0,
+    hb_stream_type_transport,
+    hb_stream_type_program
+} hb_stream_type_t;
 
 #define kMaxNumberVideoPIDS 1
-#define kMaxNumberAudioPIDS 16
+#define kMaxNumberAudioPIDS 15
 #define kMaxNumberDecodeStreams (kMaxNumberVideoPIDS+kMaxNumberAudioPIDS)
 #define kMaxNumberPMTStreams 32
 
 
 struct hb_stream_s
 {
-    char         * path;
-       FILE             * file_handle;
-       hb_stream_type_t stream_type;
-
-    int              frames;            /* video frames so far */
-    int              errors;            /* total errors so far */
-    int              last_error_frame;  /* frame # at last error message */
-    int              last_error_count;  /* # errors at last error message */
-
-    int64_t          ts_lastpcr;    /* the last pcr we found in the TS stream */
-    int64_t          ts_nextpcr;    /* the next pcr to put in a PS packet */
-
-       int                              ts_video_pids[kMaxNumberVideoPIDS];
-       int                              ts_audio_pids[kMaxNumberAudioPIDS];
-
-       int                              ts_number_video_pids;
-       int                              ts_number_audio_pids;
-
-       uint8_t         *ts_buf[kMaxNumberDecodeStreams];
-       int                              ts_pos[kMaxNumberDecodeStreams];
-       int                              ts_streamid[kMaxNumberDecodeStreams];
-       int                              ts_audio_stream_type[kMaxNumberDecodeStreams];
-       int8_t           ts_foundfirst[kMaxNumberDecodeStreams];
-       int8_t           ts_skipbad[kMaxNumberDecodeStreams];
-       int8_t           ts_streamcont[kMaxNumberDecodeStreams];
-       int8_t           ts_start[kMaxNumberDecodeStreams];
-
-       struct {
-               int lang_code;
-               int flags;
-               int rate;
-               int bitrate;
-       } a52_info[kMaxNumberAudioPIDS];
-
-       struct
-       {
-               unsigned short program_number;
-               unsigned short program_map_PID;
-       } pat_info[kMaxNumberPMTStreams];
-       int      ts_number_pat_entries;
+    int     frames;             /* video frames so far */
+    int     errors;             /* total errors so far */
+    int     last_error_frame;   /* frame # at last error message */
+    int     last_error_count;   /* # errors at last error message */
+
+    int64_t ts_lastpcr;         /* the last pcr we found in the TS stream */
+    int64_t ts_nextpcr;         /* the next pcr to put in a PS packet */
+
+    uint8_t *ts_buf[kMaxNumberDecodeStreams];
+    int     ts_pos[kMaxNumberDecodeStreams];
+    int8_t  ts_foundfirst[kMaxNumberDecodeStreams];
+    int8_t  ts_skipbad[kMaxNumberDecodeStreams];
+    int8_t  ts_streamcont[kMaxNumberDecodeStreams];
+    int8_t  ts_start[kMaxNumberDecodeStreams];
+
+    uint8_t *fwrite_buf;        /* PS buffer (set by hb_ts_stream_decode) */
+    uint8_t *fwrite_buf_orig;   /* PS buffer start (set by hb_ts_stream_decode) */
+
+    /*
+     * Stuff before this point is dynamic state updated as we read the
+     * stream. Stuff after this point is stream description state that
+     * we learn during the initial scan but cache so it can be
+     * reused during the conversion read.
+     */
+    int16_t ts_video_pids[kMaxNumberVideoPIDS];
+    int16_t ts_audio_pids[kMaxNumberAudioPIDS];
+
+    uint8_t ts_number_video_pids;
+    uint8_t ts_number_audio_pids;
+
+    uint8_t ts_streamid[kMaxNumberDecodeStreams];
+    uint8_t ts_audio_stream_type[kMaxNumberDecodeStreams];
+
+    char    *path;
+    FILE    *file_handle;
+    hb_stream_type_t stream_type;
+    int     opentype;
+
+    struct {
+        int lang_code;
+        int flags;
+        int rate;
+        int bitrate;
+    } a52_info[kMaxNumberAudioPIDS];
+
+    struct
+    {
+        unsigned short program_number;
+        unsigned short program_map_PID;
+    } pat_info[kMaxNumberPMTStreams];
+    int     ts_number_pat_entries;
 
-       struct
-       {
-               int reading;
-               unsigned char *tablebuf;
-               unsigned int tablepos;
-               unsigned char current_continuity_counter;
-
-               int section_length;
-               int program_number;
-               unsigned int PCR_PID;
-               int program_info_length;
-               unsigned char *progam_info_descriptor_data;
-               struct
-               {
-                       unsigned char stream_type;
-                       unsigned short elementary_PID;
-                       unsigned short ES_info_length;
-                       unsigned char *es_info_descriptor_data;
-               } pmt_stream_info[kMaxNumberPMTStreams];
-       } pmt_info;
+    struct
+    {
+        int reading;
+        unsigned char *tablebuf;
+        unsigned int tablepos;
+        unsigned char current_continuity_counter;
+
+        int section_length;
+        int program_number;
+        unsigned int PCR_PID;
+        int program_info_length;
+        unsigned char *progam_info_descriptor_data;
+        struct
+        {
+            unsigned char stream_type;
+            unsigned short elementary_PID;
+            unsigned short ES_info_length;
+            unsigned char *es_info_descriptor_data;
+        } pmt_stream_info[kMaxNumberPMTStreams];
+    } pmt_info;
 };
 
 /***********************************************************************
@@ -101,12 +116,35 @@ static off_t align_to_next_packet(FILE* f);
 /*
  * streams have a bunch of state that's learned during the scan. We don't
  * want to throw away the state when scan does a close then relearn
- * everything when reader does an open. So we basically ignore
- * a stream close, remember the most recent stream we've opened and only
- * delete it when a stream of a different name is opened.
+ * everything when reader does an open. So we save the stream state on
+ * the close following a scan and reuse it when 'reader' does an open.
  */
-static hb_stream_t *current_stream;
+static hb_list_t *stream_state_list;
 
+static hb_stream_t *hb_stream_lookup( const char *path )
+{
+    if ( stream_state_list == NULL )
+        return NULL;
+
+    hb_stream_t *ss;
+    int i = 0;
+
+    while ( ( ss = hb_list_item( stream_state_list, i++ ) ) != NULL )
+    {
+        if ( strcmp( path, ss->path ) == 0 )
+        {
+            break;
+        }
+    }
+    return ss;
+}
+
+static void hb_stream_state_delete( hb_stream_t *ss )
+{
+    hb_list_rem( stream_state_list, ss );
+    free( ss->path );
+    free( ss );
+}
 
 static inline int check_ps_sync(const uint8_t *buf)
 {
@@ -176,10 +214,8 @@ static int hb_stream_get_type(hb_stream_t *stream)
     return 0;
 }
 
-static void hb_stream_delete( hb_stream_t ** _d )
+static void hb_stream_delete_dynamic( hb_stream_t *d )
 {
-    hb_stream_t * d = *_d;
-
     if( d->file_handle )
     {
         fclose( d->file_handle );
@@ -196,9 +232,13 @@ static void hb_stream_delete( hb_stream_t ** _d )
                        d->ts_buf[i] = NULL;
                }
        }
+}
+
+static void hb_stream_delete( hb_stream_t *d )
+{
+    hb_stream_delete_dynamic( d );
     free( d->path );
     free( d );
-    *_d = NULL;
 }
 
 /***********************************************************************
@@ -206,32 +246,83 @@ static void hb_stream_delete( hb_stream_t ** _d )
  ***********************************************************************
  *
  **********************************************************************/
-hb_stream_t * hb_stream_open( char * path )
+hb_stream_t * hb_stream_open( char *path, int opentype )
 {
-    if (current_stream)
+
+    FILE *f = fopen( path, "r" );
+    if ( f == NULL )
     {
-        if (strcmp( path, current_stream->path ) == 0 )
-        {
-            hb_stream_seek( current_stream, 0. );
-            return current_stream;
-        }
-        hb_stream_delete( &current_stream );
+        hb_log( "hb_stream_open: open %s failed", path );
+        return NULL;
     }
+
     hb_stream_t *d = calloc( sizeof( hb_stream_t ), 1 );
+    if ( d == NULL )
+    {
+        fclose( f );
+        hb_log( "hb_stream_open: can't allocate space for %s stream state", path );
+        return NULL;
+    }
 
-    /* open the file and see if it's a type we know about. return a stream
-     * reference structure if we can deal with it & NULL otherwise. */
-    if( ( d->file_handle = fopen( path, "rb" ) ) )
+    /*
+     * if we're opening the stream to read & convert, we need
+     * the state we saved when we scanned the stream. if we're
+     * opening the stream to scan it we want to rebuild the state
+     * (even if we have saved state, the stream may have changed).
+     */
+    hb_stream_t *ss = hb_stream_lookup( path );
+    if ( opentype == 1 )
     {
+        /* opening to read - we must have saved state */
+        if ( ss == NULL )
+        {
+            hb_log( "hb_stream_open: error: re-opening %s but no scan state", path );
+            fclose( f );
+            free( d );
+            return NULL;
+        }
+        /*
+         * copy the saved state since we might be encoding the same stream
+         * multiple times.
+         */
+        memcpy( d, ss, sizeof(*d) );
+        d->file_handle = f;
+        d->opentype = opentype;
         d->path = strdup( path );
-        if (d->path != NULL &&  hb_stream_get_type( d ) != 0 )
+
+        if ( d->stream_type == hb_stream_type_transport )
         {
-            current_stream = d;
-            return d;
+            int i = 0;
+            for ( ; i < d->ts_number_video_pids + d->ts_number_audio_pids; i++)
+            {
+                d->ts_buf[i] = malloc( HB_DVD_READ_BUFFER_SIZE );
+            }
+            hb_stream_seek( d, 0. );
         }
-        fclose( d->file_handle );
-        if (d->path)
-            free( d->path );
+        return d;
+    }
+
+    /*
+     * opening for scan - delete any saved state then (re)scan the stream.
+     * If it's something we can deal with (MPEG2 PS or TS) return a stream
+     * reference structure & null otherwise.
+     */
+
+    if ( ss != NULL )
+    {
+        hb_stream_state_delete( ss );
+    }
+    d->file_handle = f;
+    d->opentype = opentype;
+    d->path = strdup( path );
+    if (d->path != NULL &&  hb_stream_get_type( d ) != 0 )
+    {
+        return d;
+    }
+    fclose( d->file_handle );
+    if (d->path)
+    {
+        free( d->path );
     }
     hb_log( "hb_stream_open: open %s failed", path );
     free( d );
@@ -252,6 +343,24 @@ void hb_stream_close( hb_stream_t ** _d )
                 stream->errors, (double)stream->errors * 100. / 
                 (double)stream->frames );
     }
+    /*
+     * if the stream was opened for a scan, cache the result, otherwise delete
+     * the state.
+     */
+    if ( stream->opentype == 0 )
+    {
+        hb_stream_delete_dynamic( stream );
+        if ( stream_state_list == NULL )
+        {
+            stream_state_list = hb_list_init();
+        }
+        hb_list_add( stream_state_list, stream );
+    }
+    else
+    {
+        hb_stream_delete( stream );
+    }
+    *_d = NULL;
 }
 
 /* when the file was first opened we made entries for all the audio elementary
@@ -960,77 +1069,57 @@ static off_t align_to_next_packet(FILE* f)
        return pos;
 }
 
-// ------------------------------------------------------------------------------------
 
-int bitpos = 0;
-unsigned int bitval = 0;
-unsigned char* bitbuf = NULL;
-unsigned int bitmask[] = {
+typedef struct {
+    uint8_t *buf;
+    uint32_t val;
+    int pos;
+} bitbuf_t;
+
+static const unsigned int bitmask[] = {
        0x0,0x1,0x3,0x7,0xf,0x1f,0x3f,0x7f,0xff,
        0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff,
        0x1ffff,0x3ffff,0x7ffff,0xfffff,0x1fffff,0x3fffff,0x7fffff,0xffffff,
        0x1ffffff,0x3ffffff,0x7ffffff,0xfffffff,0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
 
-static inline void set_buf(unsigned char* buf, int bufsize, int clear)
+static inline void set_buf(bitbuf_t *bb, uint8_t* buf, int bufsize, int clear)
 {
-       bitpos = 0;
-       bitbuf = buf;
-       bitval = (bitbuf[0] << 24) | (bitbuf[1] << 16) | (bitbuf[2] << 8) | bitbuf[3];
+       bb->pos = 0;
+       bb->buf = buf;
+       bb->val = (bb->buf[0] << 24) | (bb->buf[1] << 16) |
+              (bb->buf[2] << 8) | bb->buf[3];
        if (clear)
-               memset(bitbuf, 0, bufsize);
+               memset(bb->buf, 0, bufsize);
 }
 
-static inline int buf_size()
+static inline int buf_size(bitbuf_t *bb)
 {
-       return bitpos >> 3;
+       return bb->pos >> 3;
 }
 
-static inline void set_bits(unsigned int val, int bits)
-{
-       val &= bitmask[bits];
-
-       while (bits > 0)
-       {
-               int bitsleft = (8 - (bitpos & 7));
-               if (bits >= bitsleft)
-               {
-                       bitbuf[bitpos >> 3] |= val >> (bits - bitsleft);
-                       bitpos += bitsleft;
-                       bits -= bitsleft;
-                       val &= bitmask[bits];
-               }
-               else
-               {
-                       bitbuf[bitpos >> 3] |= val << (bitsleft - bits);
-                       bitpos += bits;
-                       bits = 0;
-               }
-       }
-}
-
-static inline unsigned int get_bits(int bits)
+static inline unsigned int get_bits(bitbuf_t *bb, int bits)
 {
        unsigned int val;
-       int left = 32 - (bitpos & 31);
+       int left = 32 - (bb->pos & 31);
 
        if (bits < left)
        {
-               val = (bitval >> (left - bits)) & bitmask[bits];
-               bitpos += bits;
+               val = (bb->val >> (left - bits)) & bitmask[bits];
+               bb->pos += bits;
        }
        else
        {
-               val = (bitval & bitmask[left]) << (bits - left);
-               bitpos += left;
+               val = (bb->val & bitmask[left]) << (bits - left);
+               bb->pos += left;
                bits -= left;
 
-               int pos = bitpos >> 3;
-               bitval = (bitbuf[pos] << 24) | (bitbuf[pos + 1] << 16) | (bitbuf[pos + 2] << 8) | bitbuf[pos + 3];
+               int pos = bb->pos >> 3;
+               bb->val = (bb->buf[pos] << 24) | (bb->buf[pos + 1] << 16) | (bb->buf[pos + 2] << 8) | bb->buf[pos + 3];
 
                if (bits > 0)
                {
-                       val |= (bitval >> (32 - bits)) & bitmask[bits];
-                       bitpos += bits;
+                       val |= (bb->val >> (32 - bits)) & bitmask[bits];
+                       bb->pos += bits;
                }
        }
 
@@ -1064,49 +1153,50 @@ static void decode_element_descriptors(hb_stream_t* stream, int esindx,
 
 int decode_program_map(hb_stream_t* stream)
 {
-       set_buf(stream->pmt_info.tablebuf, stream->pmt_info.tablepos, 0);
+    bitbuf_t bb;
+       set_buf(&bb, stream->pmt_info.tablebuf, stream->pmt_info.tablepos, 0);
 
-    get_bits(8);  // table_id
-    get_bits(4);
-    unsigned int section_length = get_bits(12);
+    get_bits(&bb, 8);  // table_id
+    get_bits(&bb, 4);
+    unsigned int section_length = get_bits(&bb, 12);
     stream->pmt_info.section_length = section_length;
 
-    unsigned int program_number = get_bits(16);
+    unsigned int program_number = get_bits(&bb, 16);
     stream->pmt_info.program_number = program_number;
-    get_bits(2);
-    get_bits(5);  // version_number
-    get_bits(1);
-    get_bits(8);  // section_number
-    get_bits(8);  // last_section_number
-    get_bits(3);
-    unsigned int PCR_PID = get_bits(13);
+    get_bits(&bb, 2);
+    get_bits(&bb, 5);  // version_number
+    get_bits(&bb, 1);
+    get_bits(&bb, 8);  // section_number
+    get_bits(&bb, 8);  // last_section_number
+    get_bits(&bb, 3);
+    unsigned int PCR_PID = get_bits(&bb, 13);
     stream->pmt_info.PCR_PID = PCR_PID;
-    get_bits(4);
-    unsigned int program_info_length = get_bits(12);
+    get_bits(&bb, 4);
+    unsigned int program_info_length = get_bits(&bb, 12);
     stream->pmt_info.program_info_length = program_info_length;
 
        int i=0;
        unsigned char *descriptor_buf = (unsigned char *) malloc(program_info_length);
        for (i = 0; i < program_info_length; i++)
        {
-         descriptor_buf[i] = get_bits(8);
+         descriptor_buf[i] = get_bits(&bb, 8);
        }
 
        int cur_pos =  9 /* data after the section length field*/ + program_info_length;
        int done_reading_stream_types = 0;
        while (!done_reading_stream_types)
        {
-         unsigned char stream_type = get_bits(8);
-                 get_bits(3);
-         unsigned int elementary_PID = get_bits(13);
-                 get_bits(4);
-         unsigned int ES_info_length = get_bits(12);
+         unsigned char stream_type = get_bits(&bb, 8);
+                 get_bits(&bb, 3);
+         unsigned int elementary_PID = get_bits(&bb, 13);
+                 get_bits(&bb, 4);
+         unsigned int ES_info_length = get_bits(&bb, 12);
 
          int i=0;
          unsigned char *ES_info_buf = (unsigned char *) malloc(ES_info_length);
          for (i=0; i < ES_info_length; i++)
          {
-               ES_info_buf[i] = get_bits(8);
+               ES_info_buf[i] = get_bits(&bb, 8);
          }
 
          if (stream_type == 0x02)
@@ -1261,17 +1351,18 @@ int decode_PAT(unsigned char *buf, hb_stream_t *stream)
             unsigned int pos = 0;
             //while (pos < tablepos)
             {
-                    set_buf(tablebuf + pos, tablepos - pos, 0);
-
-                    unsigned char section_id   = get_bits(8);
-                    get_bits(4);
-                    unsigned int section_len   = get_bits(12);
-                    get_bits(16); // transport_id
-                    get_bits(2);
-                    get_bits(5);  // version_num
-                    get_bits(1);  // current_next
-                    get_bits(8);  // section_num
-                    get_bits(8);  // last_section
+                    bitbuf_t bb;
+                    set_buf(&bb, tablebuf + pos, tablepos - pos, 0);
+
+                    unsigned char section_id   = get_bits(&bb, 8);
+                    get_bits(&bb, 4);
+                    unsigned int section_len   = get_bits(&bb, 12);
+                    get_bits(&bb, 16); // transport_id
+                    get_bits(&bb, 2);
+                    get_bits(&bb, 5);  // version_num
+                    get_bits(&bb, 1);  // current_next
+                    get_bits(&bb, 8);  // section_num
+                    get_bits(&bb, 8);  // last_section
 
                     switch (section_id)
                     {
@@ -1284,17 +1375,17 @@ int decode_PAT(unsigned char *buf, hb_stream_t *stream)
                                                  stream->ts_number_pat_entries = 0;
                           while ((curr_pos < section_len) && (stream->ts_number_pat_entries < kMaxNumberPMTStreams))
                           {
-                            unsigned int pkt_program_num = get_bits(16);
+                            unsigned int pkt_program_num = get_bits(&bb, 16);
                                                        stream->pat_info[stream->ts_number_pat_entries].program_number = pkt_program_num;
 
-                            get_bits(3);  // Reserved
+                            get_bits(&bb, 3);  // Reserved
                             if (pkt_program_num == 0)
                             {
-                              get_bits(13); // pkt_network_id
+                              get_bits(&bb, 13); // pkt_network_id
                             }
                             else
                             {
-                              unsigned int pkt_program_map_PID = get_bits(13);
+                              unsigned int pkt_program_map_PID = get_bits(&bb, 13);
                                 stream->pat_info[stream->ts_number_pat_entries].program_map_PID = pkt_program_map_PID;
                             }
                             curr_pos += 4;
@@ -1414,55 +1505,53 @@ static void hb_ts_stream_find_pids(hb_stream_t *stream)
  }
 
 
-static uint8_t *fwrite_buf;
-static uint8_t *fwrite_buf_orig;
-
-static void set_fwrite_buf( uint8_t *obuf )
+static void fwrite64( hb_stream_t *stream, void *buf, int size )
 {
-    fwrite_buf = obuf;
-    fwrite_buf_orig = obuf;
-}
-
-static void fwrite64( void* buf, int size )
-{
-    if ( (fwrite_buf - fwrite_buf_orig) + size > 2048 )
+    if ( (stream->fwrite_buf - stream->fwrite_buf_orig) + size > 2048 )
     {
         hb_log( "steam fwrite64 buffer overflow - writing %d with %d already",
-                size, fwrite_buf - fwrite_buf_orig );
+                size, stream->fwrite_buf - stream->fwrite_buf_orig );
         return;
     }
-    memcpy( fwrite_buf, buf, size );
-    fwrite_buf += size;
+    memcpy( stream->fwrite_buf, buf, size );
+    stream->fwrite_buf += size;
 }
 
 static void write_pack(hb_stream_t* stream, uint64_t time, int stuffing)
 {
-       uint8_t buf[64];
-       set_buf(buf, 64, 1);                    // clear buffer
-
-       set_bits(0x000001ba, 32);               // pack id                                                              32
-       set_bits(1, 2);                                 // 0x01                                                                 2
-       set_bits(time >> 30, 3);            // system_clock_reference_base                      3
-       set_bits(1, 1);                                 // marker_bit                                                   1
-       set_bits(time >> 15, 15);       // system_clock_reference_base                  15
-       set_bits(1, 1);                                 // marker_bit                                                   1
-       set_bits(time, 15);                     // system_clock_reference_base1                 15
-       set_bits(1, 1);                                 // marker_bit                                                   1
-       set_bits(0, 9);                     // system_clock_reference_extension         9
-       set_bits(1, 1);                                 // marker_bit                                                   1
-       set_bits(384000, 22);                   // program_mux_rate                                             22
-       set_bits(1, 1);                                 // marker_bit                                                   1
-       set_bits(1, 1);                                 // marker_bit                                                   1
-       set_bits(31, 5);                                // reserved                                                             5
-       set_bits(stuffing, 3);                  // pack_stuffing_length                                 3
-    while ( --stuffing >= 0 )
-    {
-        set_bits(0xff, 8 );
-    }
-       fwrite64(buf, buf_size());
+       uint8_t buf[24];
+
+    buf[0] = 0x00;      // pack id
+    buf[1] = 0x00;
+    buf[2] = 0x01;
+    buf[3] = 0xba;
+
+    buf[4] = 0x44 |     // SCR
+             ( ( ( time >> 30 ) & 7 ) << 3 ) |
+             ( ( time >> 28 ) & 3 );
+    buf[5] = time >> 20;
+    buf[6] = 0x04 |
+             ( ( ( time >> 15 ) & 0x1f ) << 3 ) |
+             ( ( time >> 13 ) & 3 );
+    buf[7] = time >> 5;
+    buf[8] = 0x04 | ( time << 3 );
+
+    buf[9] = 0x01;      // SCR extension
+
+    buf[10] = 384000 >> (22 - 8);     // program mux rate
+    buf[11] = (uint8_t)( 384000 >> (22 - 16) );
+    buf[12] = (uint8_t)( 384000 << 2 ) | 0x03;
+
+    buf[13] = 0xf8 | stuffing;
+
+    int i;
+    for (i = 0; i < stuffing; ++i )
+        buf[14+i] = 0xff;
+
+       fwrite64(stream, buf, 14 + stuffing );
 }
 
-static void pad_buffer(int pad)
+static void pad_buffer(hb_stream_t* stream, int pad)
 {
        pad -= 6;
 
@@ -1474,39 +1563,27 @@ static void pad_buffer(int pad)
        buf[4] = pad >> 8;
     buf[5] = pad;
 
-       fwrite64(buf, 6);
+       fwrite64(stream, buf, 6);
 
        buf[0] = 0xff;
     while ( --pad >= 0 )
     {
-               fwrite64(buf, 1);
+               fwrite64(stream, buf, 1);
        }
 }
 
-static void make_pes_header(int len, uint8_t streamid)
+static void make_pes_header(hb_stream_t* stream, int len, uint8_t streamid)
 {
        uint8_t buf[9];
-       set_buf(buf, 9, 1);                         // clear the buffer
-
-       set_bits(0x000001, 24);                         // packet_start_code_prefix                             24
-       set_bits(streamid, 8);                  // directory_stream_id                                  8
-       set_bits(len + 3, 16);                          // PES_packet_length                                    16
-       set_bits(0x2, 2);                                       // '10'                                                                 2
-       set_bits(0, 2);                                         // PES_scrambling_control                               2
-       set_bits(1, 1);                                         // PES_priority                                                 1
-       set_bits(0, 1);                                         // data_alignment_indicator                             1
-       set_bits(0, 1);                                         // copyright                                                    1
-       set_bits(0, 1);                                         // original_or_copy                                             1
-       set_bits(0, 2);                                         // PTS_DTS_flags                                                2
-       set_bits(0, 1);                                         // ESCR_flag                                                    1
-       set_bits(0, 1);                                         // ES_rate_flag                                                 1
-       set_bits(0, 1);                                         // DSM_trick_mode_flag                                  1
-       set_bits(0, 1);                                         // additional_copy_info_flag                    1
-       set_bits(0, 1);                                         // PES_CRC_flag                                                 1
-       set_bits(0, 1);                                         // PES_extension_flag                                   1
-       set_bits(0, 8);                                         // PES_header_data_length                               8
-
-    fwrite64(buf, 9);
+
+    memset(buf, 0, sizeof(buf) );
+    buf[2] = 1;
+    buf[3] = streamid;
+    buf[4] = ( len + 3 ) >> 8;
+    buf[5] = len + 3;
+    buf[6] = 0x88;
+
+    fwrite64(stream, buf, 9);
 }
 
 static void generate_output_data(hb_stream_t *stream, int curstream)
@@ -1568,7 +1645,7 @@ static void generate_output_data(hb_stream_t *stream, int curstream)
 
             // Write out the PES header
             int hdrsize = 9 + tdat[8];
-            fwrite64(tdat, hdrsize);
+            fwrite64(stream, tdat, hdrsize);
 
             // add a four byte DVD ac3 stream header
             uint8_t ac3_substream_id[4];
@@ -1577,17 +1654,17 @@ static void generate_output_data(hb_stream_t *stream, int curstream)
             ac3_substream_id[1] = 0x01;         // number of sync words
             ac3_substream_id[2] = 0x00;         // first offset (16 bits)
             ac3_substream_id[3] = 0x02;
-            fwrite64(ac3_substream_id, 4);
+            fwrite64(stream, ac3_substream_id, 4);
 
             // add the rest of the data
-            fwrite64(tdat + hdrsize, stream->ts_pos[curstream] - hdrsize);
+            fwrite64(stream, tdat + hdrsize, stream->ts_pos[curstream] - hdrsize);
         }
         else
         {
             // not audio - don't need to modify the stream so write what we've got
             tdat[4] = plen >> 8;
             tdat[5] = plen;
-            fwrite64( tdat, stream->ts_pos[curstream] );
+            fwrite64( stream,  tdat, stream->ts_pos[curstream] );
         }
     }
     else
@@ -1596,12 +1673,12 @@ static void generate_output_data(hb_stream_t *stream, int curstream)
         // PES header. AC3 audio also needs its substream header.
         if ( stream->ts_audio_stream_type[curstream] != 0x81)
         {
-            make_pes_header(stream->ts_pos[curstream],
+            make_pes_header(stream, stream->ts_pos[curstream],
                             stream->ts_streamid[curstream]);
         }
         else
         {
-            make_pes_header(stream->ts_pos[curstream] + 4,
+            make_pes_header(stream, stream->ts_pos[curstream] + 4,
                             stream->ts_streamid[curstream]);
 
             // add a four byte DVD ac3 stream header
@@ -1611,16 +1688,16 @@ static void generate_output_data(hb_stream_t *stream, int curstream)
             ac3_substream_id[1] = 0x01;         // number of sync words
             ac3_substream_id[2] = 0x00;         // first offset (16 bits)
             ac3_substream_id[3] = 0x02;
-            fwrite64(ac3_substream_id, 4);
+            fwrite64(stream, ac3_substream_id, 4);
         }
-        fwrite64( tdat, stream->ts_pos[curstream] );
+        fwrite64( stream, tdat, stream->ts_pos[curstream] );
     }
 
     // Write padding
     int left = HB_DVD_READ_BUFFER_SIZE - len;
     if ( left >= 8 )
     {
-        pad_buffer(left);
+        pad_buffer(stream, left);
     }
 
     stream->ts_pos[curstream] = 0;
@@ -1717,7 +1794,12 @@ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf )
        int curstream;
        uint8_t buf[188];
 
-    set_fwrite_buf( obuf );
+    /*
+     * stash the output buffer pointer in our stream so we don't have to
+     * pass it & its original value to everything we call.
+     */
+    stream->fwrite_buf = obuf;
+    stream->fwrite_buf_orig = obuf;
 
        // spin until we get a packet of data from some stream or hit eof
        while ( 1 )