OSDN Git Service

Cygwin: Patches for xvid and mpeg4ip Updated to work with new nasm 2.x.x
[handbrake-jp/handbrake-jp-git.git] / libhb / stream.c
index 7c57203..109864f 100755 (executable)
@@ -108,27 +108,36 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,
 static void hb_ps_stream_find_audio_ids(hb_stream_t *stream, hb_title_t *title);
 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.
+ */
+static hb_stream_t *current_stream;
+
 
 static inline int check_ps_sync(const uint8_t *buf)
 {
-    // must have a Pack header
-    // (note: the operator '&' instead of '&&' is used deliberately for better
-    // performance with a multi-issue pipeline.)
-    return (buf[0] == 0x00) & (buf[1] == 0x00) & (buf[2] == 0x01) & (buf[3] == 0xba);
+    // a legal MPEG program stream must start with a Pack header in the
+    // first four bytes.
+    return (buf[0] == 0x00) && (buf[1] == 0x00) &&
+           (buf[2] == 0x01) && (buf[3] == 0xba);
 }
 
 static inline int check_ts_sync(const uint8_t *buf)
 {
     // must have initial sync byte, no scrambling & a legal adaptation ctrl
-    return (buf[0] == 0x47) & ((buf[3] >> 6) == 0) & ((buf[3] >> 4) > 0);
+    return (buf[0] == 0x47) && ((buf[3] >> 6) == 0) && ((buf[3] >> 4) > 0);
 }
 
 static inline int have_ts_sync(const uint8_t *buf)
 {
-    return check_ts_sync(&buf[0*188]) & check_ts_sync(&buf[1*188]) &
-           check_ts_sync(&buf[2*188]) & check_ts_sync(&buf[3*188]) &
-           check_ts_sync(&buf[4*188]) & check_ts_sync(&buf[5*188]) &
-           check_ts_sync(&buf[6*188]) & check_ts_sync(&buf[7*188]);
+    return check_ts_sync(&buf[0*188]) && check_ts_sync(&buf[1*188]) &&
+           check_ts_sync(&buf[2*188]) && check_ts_sync(&buf[3*188]) &&
+           check_ts_sync(&buf[4*188]) && check_ts_sync(&buf[5*188]) &&
+           check_ts_sync(&buf[6*188]) && check_ts_sync(&buf[7*188]);
 }
 
 static int hb_stream_check_for_ts(const uint8_t *buf)
@@ -150,8 +159,8 @@ static int hb_stream_check_for_ps(const uint8_t *buf)
 {
     // program streams should have a Pack header every 2048 bytes.
     // check that we have 4 of these.
-    return check_ps_sync(&buf[0*2048]) & check_ps_sync(&buf[1*2048]) &
-           check_ps_sync(&buf[2*2048]) & check_ps_sync(&buf[3*2048]);
+    return check_ps_sync(&buf[0*2048]) && check_ps_sync(&buf[1*2048]) &&
+           check_ps_sync(&buf[2*2048]) && check_ps_sync(&buf[3*2048]);
 }
 
 static int hb_stream_get_type(hb_stream_t *stream)
@@ -177,42 +186,7 @@ static int hb_stream_get_type(hb_stream_t *stream)
     return 0;
 }
 
-/***********************************************************************
- * hb_stream_open
- ***********************************************************************
- *
- **********************************************************************/
-hb_stream_t * hb_stream_open( char * path )
-{
-    hb_stream_t * d;
-
-    d = calloc( sizeof( hb_stream_t ), 1 );
-
-    /* Open device */
-    if( ( d->file_handle = fopen( path, "rb" ) ) )
-    {
-        d->path = strdup( path );
-        if ( hb_stream_get_type( d ) != 0 )
-        {
-            return d;
-        }
-        fclose( d->file_handle );
-        free( d->path );
-    }
-    else
-    {
-        hb_log( "hb_stream_open: fopen failed (%s)", path );
-    }
-    free( d );
-    return NULL;
-}
-
-/***********************************************************************
- * hb_stream_close
- ***********************************************************************
- * Closes and frees everything
- **********************************************************************/
-void hb_stream_close( hb_stream_t ** _d )
+static void hb_stream_delete( hb_stream_t ** _d )
 {
     hb_stream_t * d = *_d;
 
@@ -245,6 +219,58 @@ void hb_stream_close( hb_stream_t ** _d )
     *_d = NULL;
 }
 
+/***********************************************************************
+ * hb_stream_open
+ ***********************************************************************
+ *
+ **********************************************************************/
+hb_stream_t * hb_stream_open( char * path )
+{
+    if (current_stream)
+    {
+        if (strcmp( path, current_stream->path ) == 0 )
+        {
+            hb_stream_seek( current_stream, 0. );
+            return current_stream;
+        }
+        hb_stream_delete( &current_stream );
+    }
+    hb_stream_t *d = calloc( sizeof( hb_stream_t ), 1 );
+
+    /* 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" ) ) )
+    {
+        d->path = strdup( path );
+        if (d->path != NULL &&  hb_stream_get_type( d ) != 0 )
+        {
+            current_stream = d;
+            return d;
+        }
+        fclose( d->file_handle );
+        if (d->path)
+            free( d->path );
+    }
+    hb_log( "hb_stream_open: open %s failed", path );
+    free( d );
+    return NULL;
+}
+
+/***********************************************************************
+ * hb_stream_close
+ ***********************************************************************
+ * Closes and frees everything
+ **********************************************************************/
+void hb_stream_close( hb_stream_t ** _d )
+{
+}
+
+/* when the file was first opened we made entries for all the audio elementary
+ * streams we found in it. Streams that were later found during the preview scan
+ * now have an audio codec, type, rate, etc., associated with them. At the end
+ * of the scan we delete all the audio entries that weren't found by the scan
+ * or don't have a format we support. This routine deletes audio entry 'indx'
+ * by copying all later entries down one slot. */
 static void hb_stream_delete_audio_entry(hb_stream_t *stream, int indx)
 {
     int i;
@@ -253,6 +279,8 @@ static void hb_stream_delete_audio_entry(hb_stream_t *stream, int indx)
     {
         stream->ts_audio_pids[indx] = stream->ts_audio_pids[i];
         stream->ts_audio_stream_type[indx] = stream->ts_audio_stream_type[i];
+        stream->ts_streamid[stream->ts_number_video_pids + indx] =
+            stream->ts_streamid[stream->ts_number_video_pids + i];
         ++indx;
     }
     --stream->ts_number_audio_pids;
@@ -381,89 +409,121 @@ static const uint8_t *hb_ts_stream_getPEStype(hb_stream_t *stream, uint32_t pid)
     return 0;
 }
 
+static uint64_t hb_ps_stream_getVideoPTS(hb_stream_t *stream)
+{
+    hb_buffer_t *buf  = hb_buffer_init(HB_DVD_READ_BUFFER_SIZE);
+    hb_list_t *list = hb_list_init();
+    // how many blocks we read while searching for a video PES header
+    int blksleft = 1024;
+    uint64_t pts = 0;
+
+    while (--blksleft >= 0 && hb_stream_read(stream, buf) == 1)
+    {
+        hb_buffer_t *es;
+
+        // 'buf' contains an MPEG2 PACK - get a list of all it's elementary streams
+        hb_demux_ps(buf, list);
+
+        while ( ( es = hb_list_item( list, 0 ) ) )
+        {
+            hb_list_rem( list, es );
+            if ( es->id == 0xe0 )
+            {
+                // this PES contains video - if there's a PTS we're done
+                // hb_demux_ps left the PTS in buf_es->start.
+                if ( es->start != ~0 )
+                {
+                    pts = es->start;
+                    blksleft = 0;
+                    break;
+                }
+            }
+            hb_buffer_close( &es );
+        }
+    }
+    hb_list_empty( &list );
+    hb_buffer_close(&buf);
+    return pts;
+}
+
 /***********************************************************************
  * hb_stream_duration
  ***********************************************************************
  *
  **********************************************************************/
-static void hb_stream_duration(hb_stream_t *stream, hb_title_t *inTitle)
+struct pts_pos {
+    uint64_t pos;   /* file position of this PTS sample */
+    uint64_t pts;   /* PTS from video stream */
+};
+
+static struct pts_pos hb_sample_pts(hb_stream_t *stream, uint64_t fpos)
 {
-       // VOB Files often have exceedingly unusual PTS values in them - they will progress for a while
-       // and then reset without warning ! 
-       if  (strstr(stream->path,".vob") != NULL) 
-       {
-               // So we'll use a 'fake duration' that should give enough time !
-               int64_t duration = 4 * 3600 * 90000;
-               inTitle->duration = duration; //90LL * dvdtime2msec( &d->pgc->playback_time );
-               inTitle->hours    = inTitle->duration / 90000 / 3600;
-               inTitle->minutes  = ( ( inTitle->duration / 90000 ) % 3600 ) / 60;
-               inTitle->seconds  = ( inTitle->duration / 90000 ) % 60;
-               return;
-       }
+    struct pts_pos pp = { 0, 0 };
 
-    uint64_t first_pts, last_pts;
-    const uint8_t *buf;
-    
+    if ( stream->stream_type == hb_stream_type_program )
+    {
+        // round address down to nearest dvd sector start
+        fpos &=~ ( HB_DVD_READ_BUFFER_SIZE - 1 );
+        fseeko( stream->file_handle, fpos, SEEK_SET );
+        pp.pts = hb_ps_stream_getVideoPTS( stream );
+    }
+    else
+    {
+        const uint8_t *buf;
+        fseeko( stream->file_handle, fpos, SEEK_SET );
+        align_to_next_packet( stream->file_handle );
+        buf = hb_ts_stream_getPEStype( stream, stream->ts_video_pids[0] );
+        if ( buf == NULL )
+        {
+            hb_log("hb_sample_pts: couldn't find video packet near %llu", fpos);
+            return pp;
+        }
+        if ( ( buf[7] >> 7 ) != 1 )
+        {
+            hb_log("hb_sample_pts: no PTS in video packet near %llu", fpos);
+            return pp;
+        }
+        pp.pts = ( ( (uint64_t)buf[9] >> 1 ) & 7 << 30 ) |
+                 ( (uint64_t)buf[10] << 22 ) |
+                 ( ( (uint64_t)buf[11] >> 1 ) << 15 ) |
+                 ( (uint64_t)buf[12] << 7 ) |
+                 ( (uint64_t)buf[13] >> 1 );
+    }
+    pp.pos = ftello(stream->file_handle);
+    hb_log("hb_sample_pts: pts %lld at %llu", pp.pts, pp.pos );
+    return pp;
+}
+
+static void hb_stream_duration(hb_stream_t *stream, hb_title_t *inTitle)
+{
     // To calculate the duration we get video presentation time stamps
     // at a couple places in the file then use their difference scaled
     // by the ratio of the distance between our measurement points &
     // the size of the file. The issue is that our video file may have
     // chunks from several different program fragments (main feature,
-    // commercials, station id, trailers, etc.) all with their on base
+    // commercials, station id, trailers, etc.) all with their own base
     // pts value. We need to difference two pts's from the same program
     // fragment. Since extraneous material is very likely at the beginning
     // and end of the content, for now we take a time stamp from 25%
     // into the file & 75% into the file then double their difference
     // to get the total duration.
+    struct pts_pos first_pts, last_pts;
+
     fseeko(stream->file_handle, 0, SEEK_END);
     uint64_t fsize = ftello(stream->file_handle);
-    fseeko(stream->file_handle, fsize >> 2, SEEK_SET);
-    align_to_next_packet(stream->file_handle);
-    buf = hb_ts_stream_getPEStype(stream, stream->ts_video_pids[0]);
-    if (buf == NULL)
-    {
-        hb_log("hb_stream_duration: couldn't find video start packet");
-        return;
-    }
-    if ((buf[7] >> 7) != 1)
-    {
-        hb_log("hb_stream_duration: no PTS in initial video packet");
-        return;
-    }
-    first_pts = ( ( (uint64_t)buf[9] >> 1 ) & 7 << 30 ) |
-                ( (uint64_t)buf[10] << 22 ) |
-                ( ( (uint64_t)buf[11] >> 1 ) << 15 ) |
-                ( (uint64_t)buf[12] << 7 ) |
-                ( (uint64_t)buf[13] >> 1 );
-    hb_log("hb_stream_duration: first pts %lld", first_pts);
-
-    // now get a pts from a frame near the end of the file.
-    fseeko(stream->file_handle, fsize - (fsize >> 2), SEEK_SET);
-    align_to_next_packet(stream->file_handle);
-    buf = hb_ts_stream_getPEStype(stream, stream->ts_video_pids[0]);
-    if (buf == NULL)
-    {
-        hb_log("hb_stream_duration: couldn't find video end packet");
-        return;
-    }
-    if ((buf[7] >> 7) != 1)
+    first_pts = hb_sample_pts(stream, fsize >> 2);
+    last_pts = hb_sample_pts(stream, fsize - (fsize >> 2) );
+
+    if ( first_pts.pos && last_pts.pos && first_pts.pos != last_pts.pos )
     {
-        hb_log("hb_stream_duration: no PTS in final video packet");
-        inTitle->duration = 0;
-        return;
+        uint64_t dur = ( ( last_pts.pts - first_pts.pts ) * fsize ) /
+                       ( last_pts.pos - first_pts.pos );
+        inTitle->duration = dur;
+        dur /= 90000;
+        inTitle->hours    = dur / 3600;
+        inTitle->minutes  = ( dur % 3600 ) / 60;
+        inTitle->seconds  = dur % 60;
     }
-    last_pts = ( ( (uint64_t)buf[9] >> 1 ) & 7 << 30 ) |
-                ( (uint64_t)buf[10] << 22 ) |
-                ( ( (uint64_t)buf[11] >> 1 ) << 15 ) |
-                ( (uint64_t)buf[12] << 7 ) |
-                ( (uint64_t)buf[13] >> 1 );
-    hb_log("hb_stream_duration: last pts %lld", last_pts);
-
-    inTitle->duration = (last_pts - first_pts) * 2 + 90000 * 60;
-    inTitle->hours    = inTitle->duration / 90000 / 3600;
-    inTitle->minutes  = ( ( inTitle->duration / 90000 ) % 3600 ) / 60;
-    inTitle->seconds  = ( inTitle->duration / 90000 ) % 60;
-
     rewind(stream->file_handle);
 }
 
@@ -490,9 +550,14 @@ int hb_stream_read( hb_stream_t * src_stream, hb_buffer_t * b )
        // Transport streams are a little more complex  - we might be able to just
        // read from the transport stream conversion buffer (if there's enough data)
        // or we may need to transfer what's left and fill it again.
-       if (src_stream->ps_decode_buffer[read_buffer_index].len - src_stream->ps_decode_buffer[read_buffer_index].read_pos > HB_DVD_READ_BUFFER_SIZE)
+       if (src_stream->ps_decode_buffer[read_buffer_index].len
+          - src_stream->ps_decode_buffer[read_buffer_index].read_pos
+        >= HB_DVD_READ_BUFFER_SIZE)
        {
-               memcpy(b->data, src_stream->ps_decode_buffer[read_buffer_index].data + src_stream->ps_decode_buffer[read_buffer_index].read_pos,HB_DVD_READ_BUFFER_SIZE);
+               memcpy(b->data,
+               src_stream->ps_decode_buffer[read_buffer_index].data +
+                 src_stream->ps_decode_buffer[read_buffer_index].read_pos,
+               HB_DVD_READ_BUFFER_SIZE);
                src_stream->ps_decode_buffer[read_buffer_index].read_pos += HB_DVD_READ_BUFFER_SIZE;
                return 1;
        }
@@ -504,9 +569,9 @@ int hb_stream_read( hb_stream_t * src_stream, hb_buffer_t * b )
                int amt_avail_to_transfer = src_stream->ps_decode_buffer[read_buffer_index].len - src_stream->ps_decode_buffer[read_buffer_index].read_pos;
                memcpy(b->data, src_stream->ps_decode_buffer[read_buffer_index].data + src_stream->ps_decode_buffer[read_buffer_index].read_pos, amt_avail_to_transfer);
                transfer_size -= amt_avail_to_transfer;
-               src_stream->ps_decode_buffer[read_buffer_index].read_pos += amt_avail_to_transfer;
-               
+
                // Give up this buffer - decoding may well need it, and we're done
+               src_stream->ps_decode_buffer[read_buffer_index].read_pos = 0;
                src_stream->ps_decode_buffer[read_buffer_index].write_pos = 0;
                src_stream->ps_decode_buffer[read_buffer_index].len = 0;
                
@@ -546,6 +611,7 @@ int hb_stream_seek( hb_stream_t * src_stream, float f )
   fseeko(src_stream->file_handle,0 ,SEEK_END);
   stream_size = ftello(src_stream->file_handle);
   new_pos = (off_t) ((double) (stream_size) * pos_ratio);
+  new_pos &=~ (HB_DVD_READ_BUFFER_SIZE - 1);
   int r = fseeko(src_stream->file_handle, new_pos, SEEK_SET);
   
   if (r == -1)
@@ -609,16 +675,18 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,
                    stream->ts_audio_stream_type[aud_pid_index],
                    audio->id);
             stream->ts_audio_stream_type[aud_pid_index] = 0x81;
+            stream->ts_streamid[stream->ts_number_video_pids + aud_pid_index] = buf[3];
         }
         else if ((buf[3] & 0xe0) == 0xc0)
         {
-            audio->id = buf[3];
+            audio->id = buf[3] | aud_pid_index;
             audio->codec = HB_ACODEC_MPGA;
             hb_log("transport stream pid 0x%x (type 0x%x) is MPEG audio id 0x%x",
                    stream->ts_audio_pids[aud_pid_index],
                    stream->ts_audio_stream_type[aud_pid_index],
                    audio->id);
             stream->ts_audio_stream_type[aud_pid_index] = 0x03;
+            stream->ts_streamid[stream->ts_number_video_pids + aud_pid_index] = buf[3];
         }
     }
     fseeko(stream->file_handle, cur_pos, SEEK_SET);
@@ -640,20 +708,25 @@ static void add_audio_to_title(hb_title_t *title, int id)
     {
         case 0x0:
             audio->codec = HB_ACODEC_MPGA;
-            hb_log("hb_ps_stream_find_audio_ids: added MPEG audio stream 0x%x", id);
+            hb_log("add_audio_to_title: added MPEG audio stream 0x%x", id);
             break;
         case 0x2:
-            audio->codec = HB_ACODEC_LPCM;
-            hb_log("hb_ps_stream_find_audio_ids: added LPCM audio stream 0x%x", id);
-            break;
-        case 0x4:
-            audio->codec = HB_ACODEC_DCA;
-            hb_log("hb_ps_stream_find_audio_ids: added DCA audio stream 0x%x", id);
-            break;
+            // type 2 is a DVD subtitle stream - just ignore it */
+            free( audio );
+            return;
         case 0x8:
             audio->codec = HB_ACODEC_AC3;
-            hb_log("hb_ps_stream_find_audio_ids: added AC3 audio stream 0x%x", id);
+            hb_log("add_audio_to_title: added AC3 audio stream 0x%x", id);
             break;
+        case 0xa:
+            audio->codec = HB_ACODEC_LPCM;
+            hb_log("add_audio_to_title: added LPCM audio stream 0x%x", id);
+            break;
+        default:
+            hb_log("add_audio_to_title: unknown audio stream type 0x%x", id);
+            free( audio );
+            return;
+
     }
     hb_list_add( title->list_audio, audio );
 }
@@ -664,14 +737,16 @@ static void hb_ps_stream_find_audio_ids(hb_stream_t *stream, hb_title_t *title)
     hb_buffer_t *buf  = hb_buffer_init(HB_DVD_READ_BUFFER_SIZE);
     hb_list_t *list = hb_list_init();
     // how many blocks we read while searching for audio streams
-    int blksleft = 2048;
+    int blksleft = 4096;
     // there can be at most 16 unique streams in an MPEG PS (8 in a DVD)
     // so we use a bitmap to keep track of the ones we've already seen.
     // Bit 'i' of smap is set if we've already added the audio for
     // audio substream id 'i' to the title's audio list.
     uint32_t smap = 0;
 
-    hb_stream_seek(stream, 0.0f);
+    // start looking 20% into the file since there's occasionally no
+    // audio at the beginning (particularly for vobs).
+    hb_stream_seek(stream, 0.2f);
                
     while (--blksleft >= 0 && hb_stream_read(stream, buf) == 1)
     {
@@ -715,14 +790,23 @@ void hb_stream_update_audio(hb_stream_t *stream, hb_audio_t *audio)
        
     if (stream->stream_type == hb_stream_type_transport)
        {
-               // Find the audio stream info for this PID
-        int i = (audio->id >> 8) & 0xf;
+        // Find the audio stream info for this PID. The stream index is
+        // the subchannel id which is in the bottom four bits for MPEG audio
+        // and the bottom four bits of the upper byte for everything else.
+        int i = ( audio->id >= 0xd0 ? audio->id >> 8 : audio->id ) & 0xf;
         if (i >= stream->ts_number_audio_pids)
                {
             hb_log("hb_stream_update_audio: no PID for audio stream 0x%x",
                     audio->id);
                        return;
                }
+        if (audio->id < 0xd0)
+        {
+            /* XXX fake mpeg audio sample rate & bps */
+            stream->a52_info[i].flags = A52_STEREO;
+            stream->a52_info[i].rate = 48000 /*Hz*/;
+            stream->a52_info[i].bitrate = 384000 /*Bps*/;
+        }
                
                lang = lang_for_code(stream->a52_info[i].lang_code);
                if (!audio->rate)
@@ -789,7 +873,7 @@ void hb_stream_update_audio(hb_stream_t *stream, hb_audio_t *audio)
        }
        
        snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name,
-         audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec == HB_ACODEC_MPGA ? "MPEG" : "LPCM" ) );
+         audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec == HB_ACODEC_MPGA ? "MPEG" : ( audio->codec == HB_ACODEC_DCA ? "DTS" : "LPCM" ) ) );
        snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s", strlen(lang->native_name) ? lang->native_name : lang->eng_name );
        snprintf( audio->iso639_2, sizeof( audio->iso639_2 ), "%s", lang->iso639_2);
 
@@ -879,7 +963,6 @@ static void hb_ts_stream_init(hb_stream_t *stream)
        for (i = stream->ts_number_video_pids; i < stream->ts_number_video_pids + stream->ts_number_audio_pids; i++)
        {
                stream->ts_packetbuf[i] = (unsigned char *) malloc(1024 * 1024);
-               stream->ts_streamid[i] = 0xBD;          // Stream 1 is AC-3 Audio
        }
 }
 
@@ -1028,24 +1111,24 @@ int decode_program_map(hb_stream_t* stream)
 {
        set_buf(stream->pmt_info.tablebuf, stream->pmt_info.tablepos, 0);
 
-       unsigned char table_id  = get_bits(8);
-                                                                                                                         get_bits(4);
-       unsigned int section_length = get_bits(12);
-       stream->pmt_info.section_length = section_length;
-       
-       unsigned int program_number = get_bits(16);
-       stream->pmt_info.program_number = program_number;
-                                                                                                                               get_bits(2);
-       unsigned char version_number = get_bits(5);
-                                                                                                                         get_bits(1);
-       unsigned char section_number = get_bits(8);
-       unsigned char last_section_number = get_bits(8);
-                                                                                                                         get_bits(3);
-       unsigned int PCR_PID = get_bits(13);
-       stream->pmt_info.PCR_PID = PCR_PID;
-                                                                                                                         get_bits(4);
-       unsigned int program_info_length = get_bits(12);
-       stream->pmt_info.program_info_length = program_info_length;
+    get_bits(8);  // table_id
+    get_bits(4);
+    unsigned int section_length = get_bits(12);
+    stream->pmt_info.section_length = section_length;
+
+    unsigned int program_number = get_bits(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);
+    stream->pmt_info.PCR_PID = PCR_PID;
+    get_bits(4);
+    unsigned int program_info_length = get_bits(12);
+    stream->pmt_info.program_info_length = program_info_length;
 
        int i=0;
        unsigned char *descriptor_buf = (unsigned char *) malloc(program_info_length);
@@ -1226,14 +1309,14 @@ int decode_PAT(unsigned char *buf, hb_stream_t *stream)
                     set_buf(tablebuf + pos, tablepos - pos, 0);
 
                     unsigned char section_id   = get_bits(8);
-                                                                              get_bits(4);
+                    get_bits(4);
                     unsigned int section_len   = get_bits(12);
-                    unsigned int transport_id  = get_bits(16);
-                                                                              get_bits(2);
-                    unsigned int version_num   = get_bits(5);
-                    unsigned int current_next  = get_bits(1);
-                    unsigned int section_num   = get_bits(8);
-                    unsigned int last_section  = get_bits(8);
+                    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
 
                     switch (section_id)
                     {
@@ -1252,7 +1335,7 @@ int decode_PAT(unsigned char *buf, hb_stream_t *stream)
                             get_bits(3);  // Reserved
                             if (pkt_program_num == 0)
                             {
-                              unsigned int pkt_network_PID = get_bits(13);
+                              get_bits(13); // pkt_network_id
                             }
                             else
                             {
@@ -1510,21 +1593,8 @@ int generate_output_data(hb_stream_t *stream, int write_ac3, int curstream, int
                                        return 1;
                                }
 
-                               int index_of_selected_pid = -1;
-                               if ((index_of_selected_pid = index_of_video_pid(pid,stream)) < 0)
-                               {
-                                       if ((index_of_selected_pid = index_of_audio_pid(pid,stream)) < 0)
-                                       {
-                                               hb_log("generate_output_data - cannot find pid 0x%x (%d) in selected audio or video pids", pid, pid);
-                                               return 0;
-                                       }
-                                       else
-                                       {
-                                               stream->ts_packetbuf[curstream][pos + 3] = stream->ts_streamid[stream->ts_number_video_pids + index_of_selected_pid];
-                                       }
-                               }
-                               else
-                                       stream->ts_packetbuf[curstream][pos + 3] = stream->ts_streamid[index_of_selected_pid];
+                stream->ts_packetbuf[curstream][pos + 3] =
+                    stream->ts_streamid[curstream];
 
                                // Packet length..
                                // Subtract pack size (14) and pes id and len (6) from lenth
@@ -1578,10 +1648,12 @@ int generate_output_data(hb_stream_t *stream, int write_ac3, int curstream, int
 
                                // Add pes header for next packet
                                pos -= 9;
-//                             make_pes_header(stream->ts_packetbuf[curstream] + pos, (pid == stream->ts_video_pids[0] ? stream->ts_streamid[kVideoStream] : stream->ts_streamid[kAudioStream]), 0, -1, -1);
                                make_pes_header(stream->ts_packetbuf[curstream] + pos, stream->ts_streamid[curstream], 0, -1, -1);
                        }
 
+                       stream->ts_packetpos[curstream] = 0;
+                       stream->ts_streamcont[curstream] = -1;
+
                        // Write padding
                        if ((written % HB_DVD_READ_BUFFER_SIZE) != 0)
                        {
@@ -1595,9 +1667,6 @@ int generate_output_data(hb_stream_t *stream, int write_ac3, int curstream, int
                                }
                        }
 
-                       stream->ts_packetpos[curstream] = 0;
-                       stream->ts_streamcont[curstream] = -1;
-
        return 0;
 }
 
@@ -1640,9 +1709,7 @@ static int hb_ts_handle_ac3_audio(hb_stream_t *stream, int curstream, unsigned c
 
        // Check the next packet to make sure IT starts with a 0x0b77
        int plen = 0;
-//                                     if (buf[4 + adapt_len] == 0 && buf[4 + adapt_len + 1] == 0 &&           // Starting with an mpeg header?
-//                                             buf[4 + adapt_len + 2] == 1 && buf[4 + adapt_len + 3] == 0xBD)
-                       plen = 9 + buf[4 + adapt_len + 8];
+    plen = 9 + buf[4 + adapt_len + 8];
        int pstart = 4 + adapt_len + plen;
        if (buf[pstart] != 0x0b || buf[pstart + 1] != 0x77)
        {
@@ -1923,7 +1990,6 @@ static void hb_ts_stream_decode(hb_stream_t *stream)
                        {
                                stream->ts_skipbad[i] = 1;
                        }
-               //      stream->ts_skipbad[kAudioStream] = stream->ts_skipbad[kVideoStream] = 1;
                        continue;
                }
                else if (adaption == 0x2)
@@ -1933,19 +1999,19 @@ static void hb_ts_stream_decode(hb_stream_t *stream)
                        adapt_len = buf[4] + 1;
                        if (adapt_len > 184)
                        {
-                               hb_log("hb_ts_stream_decode - Invalid adapt len (was > 183)!");
+                               hb_log("hb_ts_stream_decode - Invalid adapt len %d", adapt_len);
                                for (i=0; i < stream->ts_number_video_pids + stream->ts_number_audio_pids; i++)
                                {
                                        stream->ts_skipbad[i] = 1;
                                }
-//                             stream->ts_skipbad[kAudioStream] = stream->ts_skipbad[kVideoStream] = 1;
                        }
                }
 
                // HBO is slick, it doesn't bother to sync AC3 packets with PES elementary stream packets.. so
                // we have to swizzle them together!  (ARGHH!)
-//             if (pid == stream->ts_audio_pids[0] && start)
-               if ((index_of_audio_pid(pid, stream) >= 0) && start)
+               if (start && curstream >= stream->ts_number_video_pids &&
+            stream->ts_audio_stream_type[curstream - stream->ts_number_video_pids]
+              != 0x03)
                {
                        // Is there an AC3 packet start 0b77 code in this packet??
                        int sync_found = 0;
@@ -1963,10 +2029,7 @@ static void hb_ts_stream_decode(hb_stream_t *stream)
                        // Couldn't find an AC3 sync start in this packet.. don't make a PES packet!
                        if (!sync_found)
                        {
-//                                     int pos = ftell(fin);
-//                                     error("AC3 packet sync not found in start frame");
-//                                     return 1;
-                               adapt_len += 9 + buf[4 + adapt_len + 8];        
+                               adapt_len = 184;        
                                start = 0;
                        }
                }
@@ -1977,7 +2040,6 @@ static void hb_ts_stream_decode(hb_stream_t *stream)
                        // Check to see if this is an i_frame (group of picture start)
                        if (pid == stream->ts_video_pids[0])
                        {
-//                                printf("Found Video Start for pid 0x%x\n", pid);
                                // Look for the Group of Pictures packet.. indicates this is an I-Frame packet..
                                doing_iframe = 0;
                                unsigned int strid = 0;
@@ -1999,8 +2061,6 @@ static void hb_ts_stream_decode(hb_stream_t *stream)
                                                // picture_header, let's see if it's an I-frame
                                                if (i<187)
                                                {
-//                                                     int pic_start_code = (buf[i+2] >> 3) & 0x07;
-//                                                     hb_log("hb_ts_stream_decode - picture_start_code header value = 0x%x (%d)", pic_start_code, pic_start_code);
                                                        // check if picture_coding_type == 1
                                                        if ((buf[i+2] & (0x7 << 3)) == (1 << 3))
                                                        {
@@ -2045,8 +2105,7 @@ static void hb_ts_stream_decode(hb_stream_t *stream)
                {
                        // Save the substream id block so we can added it to subsequent blocks
                        int write_ac3 = 0;
-//                     if (pid == stream->ts_audio_pids[0] /*&& audstreamid == 0xBD*/)
-                       if (index_of_audio_pid(pid, stream) >= 0)
+            if (curstream >= stream->ts_number_video_pids)
                        {
                                // Curstream is a zero based index of streams and includes both video and audio streams, so we must subtract the numver of video streams
                                // from the indes value used here since ts_audio_stream_type is indexed only by audio streams.
@@ -2065,8 +2124,17 @@ static void hb_ts_stream_decode(hb_stream_t *stream)
                }
 
                // Add the payload for this packet to the current buffer
-               if (stream->ts_foundfirst[curstream] && (184 - adapt_len) > 0)
+               if (!stream->ts_skipbad[curstream] && stream->ts_foundfirst[curstream] &&
+            (184 - adapt_len) > 0)
                {
+            // XXX this shouldn't happen but we'll be paranoid
+            if (stream->ts_packetpos[curstream] + 184 - adapt_len > 1024*1024)
+            {
+                hb_log("hb_ts_stream_decode: ts_packetbuf overflow, pos = %d ,"
+                       "len = %d", stream->ts_packetpos[curstream],
+                       184 - adapt_len );
+                return;
+            }
                        memcpy(stream->ts_packetbuf[curstream] + stream->ts_packetpos[curstream], buf + 4 + adapt_len, 184 - adapt_len);
                        stream->ts_packetpos[curstream] += 184 - adapt_len;
                }