All pastes #995496 Raw Edit

someone

public text v1 · immutable
#995496 ·published 2008-04-24 06:51 UTC
rendered paste body
Index: libhb/stream.c===================================================================--- libhb/stream.c	(revision 1432)+++ libhb/stream.c	(working copy)@@ -14,8 +14,9 @@  typedef enum {     hb_stream_type_unknown = 0,-    hb_stream_type_transport,-    hb_stream_type_program+    transport,+    program,+    dvd_program } hb_stream_type_t;  #define kMaxNumberVideoPIDS 1@@ -30,10 +31,12 @@     int     errors;             /* total errors so far */     int     last_error_frame;   /* frame # at last error message */     int     last_error_count;   /* # errors at last error message */+    int     packetsize;         /* Transport Stream packet size */      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_packet;         /* buffer for one TS packet */     uint8_t *ts_buf[kMaxNumberDecodeStreams];     int     ts_pos[kMaxNumberDecodeStreams];     int8_t  ts_foundfirst[kMaxNumberDecodeStreams];@@ -50,19 +53,18 @@      * we learn during the initial scan but cache so it can be      * reused during the conversion read.      */+    uint8_t ts_number_video_pids;+    uint8_t ts_number_audio_pids;+     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_video_stream_type[kMaxNumberDecodeStreams];-    uint8_t ts_audio_stream_type[kMaxNumberDecodeStreams];+    uint8_t ts_stream_type[kMaxNumberDecodeStreams];      char    *path;     FILE    *file_handle;-    hb_stream_type_t stream_type;+    hb_stream_type_t hb_stream_type;     int     opentype;      struct {@@ -112,7 +114,7 @@ static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,                                                        int aud_pid_index); 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);+static off_t align_to_next_packet(hb_stream_t *stream);  /*  * streams have a bunch of state that's learned during the scan. We don't@@ -147,47 +149,124 @@     free( ss ); } -static inline int check_ps_sync(const uint8_t *buf)+/*+ * logging routines.+ * these frontend hb_log because transport streams can have a lot of errors+ * so we want to rate limit messages. this routine limits the number of+ * messages to at most one per minute of video. other errors that occur+ * during the minute are counted & the count is output with the next+ * error msg we print.+ */+static void ts_warn_helper( hb_stream_t *stream, char *log, va_list args ) {+    // limit error printing to at most one per minute of video (at 30fps)+    ++stream->errors;+    if ( stream->frames - stream->last_error_frame >= 30*60 )+    {+        char msg[256];++        vsnprintf( msg, sizeof(msg), log, args );++        if ( stream->errors - stream->last_error_count < 10 )+        {+            hb_log( "stream: error near frame %d: %s", stream->frames, msg );+        }+        else+        {+            int Edelta = stream->errors - stream->last_error_count;+            double Epcnt = (double)Edelta * 100. /+                            (stream->frames - stream->last_error_frame);+            hb_log( "stream: %d new errors (%.0f%%) up to frame %d: %s",+                    Edelta, Epcnt, stream->frames, msg );+        }+        stream->last_error_frame = stream->frames;+        stream->last_error_count = stream->errors;+    }+}++static void ts_warn( hb_stream_t *stream, char *log, ... )+{+    va_list     args;+    va_start( args, log );+    ts_warn_helper( stream, log, args );+    va_end( args );+}++static void ts_err( hb_stream_t *stream, int curstream, char *log, ... )+{+    va_list     args;+    va_start( args, log );+    ts_warn_helper( stream, log, args );+    va_end( args );++    stream->ts_skipbad[curstream] = 1;+    stream->ts_pos[curstream] = 0;+    stream->ts_streamcont[curstream] = -1;+}++static int check_ps_sync(const uint8_t *buf)+{     // 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)+static int check_ps_sys(const uint8_t *buf) {+    // a legal MPEG program stream must start with a Pack followed by a+    // SYS. If we've already verified the pack, this skips over it and checks+    // for the sys header.+    int pos = 14 + ( buf[13] & 0x7 );   // skip over the PACK+    return (buf[pos+0] == 0x00) && (buf[pos+1] == 0x00) &&+           (buf[pos+2] == 0x01) && (buf[pos+3] == 0xbb);+}++static 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); } -static inline int have_ts_sync(const uint8_t *buf)+static int have_ts_sync(const uint8_t *buf, int psize) {-    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*psize]) && check_ts_sync(&buf[1*psize]) &&+           check_ts_sync(&buf[2*psize]) && check_ts_sync(&buf[3*psize]) &&+           check_ts_sync(&buf[4*psize]) && check_ts_sync(&buf[5*psize]) &&+           check_ts_sync(&buf[6*psize]) && check_ts_sync(&buf[7*psize]); }  static int hb_stream_check_for_ts(const uint8_t *buf) {     // transport streams should have a sync byte every 188 bytes.-    // search the first KB of buf looking for at least 8 consecutive+    // search the first 8KB of buf looking for at least 8 consecutive     // correctly located sync patterns.     int offset = 0; -    for ( offset = 0; offset < 1024; ++offset )+    for ( offset = 0; offset < 8*1024-8*188; ++offset )     {-        if ( have_ts_sync( &buf[offset]) )-            return 1;+        if ( have_ts_sync( &buf[offset], 188) )+            return 188 | (offset << 8);+        if ( have_ts_sync( &buf[offset], 192) )+            return 192 | (offset << 8);+        if ( have_ts_sync( &buf[offset], 204) )+            return 204 | (offset << 8);+        if ( have_ts_sync( &buf[offset], 208) )+            return 208 | (offset << 8);     }     return 0; }  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.+    // program streams should start with a PACK then a SYS header.+    return check_ps_sync(buf) && check_ps_sys(buf);+}++static int hb_stream_check_for_dvd_ps(const uint8_t *buf)+{+    // DVD program streams should have a Pack header every 2048 bytes.+    // check that we have 4 of these in a row.     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]); }@@ -198,17 +277,28 @@      if ( fread(buf, 1, sizeof(buf), stream->file_handle) == sizeof(buf) )     {-        if ( hb_stream_check_for_ts(buf) != 0 )+        int psize;+        if ( ( psize = hb_stream_check_for_ts(buf) ) != 0 )         {-            hb_log("file is MPEG Transport Stream");-            stream->stream_type = hb_stream_type_transport;+            int offset = psize >> 8;+            psize &= 0xff;+            hb_log("file is MPEG Transport Stream with %d byte packets"+                   " offset %d bytes", psize, offset);+            stream->packetsize = psize;+            stream->hb_stream_type = transport;             hb_ts_stream_init(stream);             return 1;         }+        if ( hb_stream_check_for_dvd_ps(buf) != 0 )+        {+            hb_log("file is MPEG DVD Program Stream");+            stream->hb_stream_type = dvd_program;+            return 1;+        }         if ( hb_stream_check_for_ps(buf) != 0 )         {             hb_log("file is MPEG Program Stream");-            stream->stream_type = hb_stream_type_program;+            stream->hb_stream_type = program;             return 1;         }     }@@ -225,6 +315,11 @@  	int i=0; +    if ( d->ts_packet )+    {+        free( d->ts_packet );+        d->ts_packet = NULL;+    } 	for (i = 0; i < kMaxNumberDecodeStreams; i++) 	{ 		if (d->ts_buf[i])@@ -291,8 +386,10 @@         d->opentype = opentype;         d->path = strdup( path ); -        if ( d->stream_type == hb_stream_type_transport )+        if ( d->hb_stream_type == transport )         {+            d->ts_packet = malloc( d->packetsize );+             int i = 0;             for ( ; i < d->ts_number_video_pids + d->ts_number_audio_pids; i++)             {@@ -308,7 +405,6 @@      * 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 );@@ -377,7 +473,7 @@     for (i = indx+1; i < stream->ts_number_audio_pids; ++i)     {         stream->ts_audio_pids[indx] = stream->ts_audio_pids[i];-        stream->ts_audio_stream_type[1 + indx] = stream->ts_audio_stream_type[1+i];+        stream->ts_stream_type[1 + indx] = stream->ts_stream_type[1+i];         stream->ts_streamid[1 + indx] = stream->ts_streamid[1 + i];         ++indx;     }@@ -438,7 +534,7 @@     //   the elementary stream is an audio type.     // - For program streams read the first 4MB and take every unique     //   audio stream we find.-	if (stream->stream_type == hb_stream_type_transport)+	if (stream->hb_stream_type == transport) 	{         int i; @@ -471,27 +567,80 @@ }  /*+ * read the next transport stream packet from 'stream'. Return NULL if+ * we hit eof & a pointer to the sync byte otherwise.+ */+static const uint8_t *next_packet( hb_stream_t *stream )+{+    uint8_t *buf = stream->ts_packet + stream->packetsize - 188;++    while ( 1 )+    {+        if ( fread(stream->ts_packet, 1, stream->packetsize, stream->file_handle) !=+             stream->packetsize )+        {+            return NULL;+        }+        if (buf[0] == 0x47)+        {+            return buf;+        }+        // lost sync - back up to where we started then try to re-establish.+        off_t pos = ftello(stream->file_handle) - stream->packetsize;+        off_t pos2 = align_to_next_packet(stream);+        if ( pos2 == 0 )+        {+            hb_log( "next_packet: eof while re-establishing sync @ %lld", pos );+            return NULL;+        }+        ts_warn( stream, "next_packet: sync lost @ %lld, regained after %lld bytes",+                 pos, pos2 );+    }+}++/*+ * skip to the start of the next PACK header in program stream src_stream.+ */+static void skip_to_next_pack( hb_stream_t *src_stream )+{+    // scan forward until we find the start of the next pack+    uint32_t strt_code = -1;+    int c;++    flockfile( src_stream->file_handle );+    while ( ( c = getc_unlocked( src_stream->file_handle ) ) != EOF )+    {+        strt_code = ( strt_code << 8 ) | c;+        if ( strt_code == 0x000001ba )+            // we found the start of the next pack+            break;+    }+    funlockfile( src_stream->file_handle );++    // if we didn't terminate on an eof back up so the next read+    // starts on the pack boundary.+    if ( c != EOF )+    {+        fseeko( src_stream->file_handle, -4, SEEK_CUR );+    }+}++/*  * scan the next MB of 'stream' to find the next start packet for  * the Packetized Elementary Stream associated with TS PID 'pid'.  */ static const uint8_t *hb_ts_stream_getPEStype(hb_stream_t *stream, uint32_t pid) {-    static uint8_t buf[188];     int npack = 100000; // max packets to read      while (--npack >= 0)     {-        if (fread(buf, 1, 188, stream->file_handle) != 188)+        const uint8_t *buf = next_packet( stream );+        if ( buf == NULL )         {             hb_log("hb_ts_stream_getPEStype: EOF while searching for PID 0x%x", pid);             return 0;         }-        if (buf[0] != 0x47)-        {-            hb_log("hb_ts_stream_getPEStype: lost sync while searching for PID 0x%x", pid);-            align_to_next_packet(stream->file_handle);-            continue;-        }          /*          * The PES header is only in TS packets with 'start' set so we check@@ -541,7 +690,7 @@         hb_buffer_t *es;          // 'buf' contains an MPEG2 PACK - get a list of all it's elementary streams-        hb_demux_ps(buf, list, 0);+        hb_demux_ps( buf, list, 0 );          while ( ( es = hb_list_item( list, 0 ) ) )         {@@ -604,18 +753,11 @@ {     struct pts_pos pp = { 0, 0 }; -    if ( stream->stream_type == hb_stream_type_program )+    if ( stream->hb_stream_type == transport )     {-        // 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 );+        align_to_next_packet( stream );         buf = hb_ts_stream_getPEStype( stream, stream->ts_video_pids[0] );         if ( buf == NULL )         {@@ -633,8 +775,18 @@                  ( (uint64_t)buf[12] << 7 ) |                  ( (uint64_t)buf[13] >> 1 );     }+    else+    {+        // round address down to nearest dvd sector start+        fpos &=~ ( HB_DVD_READ_BUFFER_SIZE - 1 );+        fseeko( stream->file_handle, fpos, SEEK_SET );+        if ( stream->hb_stream_type == program )+        {+            skip_to_next_pack( stream );+        }+        pp.pts = hb_ps_stream_getVideoPTS( stream );+    }     pp.pos = ftello(stream->file_handle);-    hb_log("hb_sample_pts: pts %lld at %llu", pp.pts, pp.pos );     return pp; } @@ -716,12 +868,59 @@  **********************************************************************/ int hb_stream_read( hb_stream_t * src_stream, hb_buffer_t * b ) {-    if ( src_stream->stream_type == hb_stream_type_program )+    if ( src_stream->hb_stream_type == dvd_program )     {         size_t amt_read = fread(b->data, HB_DVD_READ_BUFFER_SIZE, 1,                                 src_stream->file_handle);         return (amt_read > 0);     }+    if ( src_stream->hb_stream_type == program )+    {+        // a general program stream has arbitrary sized pack's. we're+        // currently positioned at the start of a pack so read up to but+        // not including the start of the next, expanding the buffer+        // as necessary.+        uint8_t *cp = b->data;+        uint8_t *ep = cp + b->alloc;+        uint32_t strt_code = -1;+        int c;++        // consume the first byte of the initial pack so we don't match on+        // it in the loop below.+        if ( ( c = getc( src_stream->file_handle ) ) == EOF )+            return 0;++        *cp++ = c;++        flockfile( src_stream->file_handle );+        while ( ( c = getc_unlocked( src_stream->file_handle ) ) != EOF )+        {+            strt_code = ( strt_code << 8 ) | c;+            if ( strt_code == 0x000001ba )+                // we found the start of the next pack+                break;+            if ( cp >= ep )+            {+                // need to expand the buffer+                int curSize = cp - b->data;+                hb_buffer_realloc( b, curSize * 2 );+                cp = b->data + curSize;+                ep = b->data + b->alloc;+            }+            *cp++ = c;+        }+        funlockfile( src_stream->file_handle );++        // if we didn't terminate on an eof back up so the next read+        // starts on the pack boundary.+        b->size = cp - b->data;+        if ( c != EOF )+        {+            fseeko( src_stream->file_handle, -4, SEEK_CUR );+            b->size -= 4;+        }+        return 1;+    }     return hb_ts_stream_decode( src_stream, b->data ); } @@ -732,29 +931,33 @@  **********************************************************************/ int hb_stream_seek( hb_stream_t * src_stream, float f ) {-  off_t stream_size, cur_pos, new_pos;-  double pos_ratio = f;-  cur_pos = ftello(src_stream->file_handle);-  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);+    off_t stream_size, cur_pos, new_pos;+    double pos_ratio = f;+    cur_pos = ftello( src_stream->file_handle );+    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); -  if (r == -1)-  {-    fseeko(src_stream->file_handle, cur_pos, SEEK_SET);-    return 0;-  }+    int r = fseeko( src_stream->file_handle, new_pos, SEEK_SET );+    if (r == -1)+    {+        fseeko( src_stream->file_handle, cur_pos, SEEK_SET );+        return 0;+    } -  if (src_stream->stream_type == hb_stream_type_transport)-  {-	// We need to drop the current decoder output and move-	// forwards to the next transport stream packet.-	hb_ts_stream_reset(src_stream);-  }+    if ( src_stream->hb_stream_type == transport )+    {+        // We need to drop the current decoder output and move+        // forwards to the next transport stream packet.+        hb_ts_stream_reset(src_stream);+    }+    else if ( src_stream->hb_stream_type == program )+    {+        skip_to_next_pack( src_stream );+    } -  return 1;+    return 1; }  static void set_audio_description( hb_audio_t *audio, iso639_lang_t *lang )@@ -785,7 +988,7 @@     const uint8_t *buf;      fseeko(stream->file_handle, 0, SEEK_SET);-    align_to_next_packet(stream->file_handle);+    align_to_next_packet(stream);     buf = hb_ts_stream_getPEStype(stream, stream->ts_audio_pids[aud_pid_index]);      /* check that we found a PES header */@@ -797,20 +1000,49 @@             audio->config.in.codec = HB_ACODEC_AC3;             hb_log("transport stream pid 0x%x (type 0x%x) is AC-3 audio id 0x%x",                    stream->ts_audio_pids[aud_pid_index],-                   stream->ts_audio_stream_type[1 + aud_pid_index],+                   stream->ts_stream_type[1 + aud_pid_index],                    audio->id);-            stream->ts_audio_stream_type[1 + aud_pid_index] = 0x81;-            stream->ts_streamid[1 + aud_pid_index] = buf[3];+            stream->ts_stream_type[1 + aud_pid_index] = 0x81;+            stream->ts_streamid[1 + aud_pid_index] = 0xbd;         }+        else if (buf[3] == 0xfd)+        {+            /* XXX Extended stream id (ISO 13818-1(2000) Amd 2) - we have to look+             * inside the PES extension to find out the real stream id then+             * figure out what the heck it means. For now we just use the stream+             * type if one was specified. */+            const char *atype = 0;+            switch (stream->ts_stream_type[1 + aud_pid_index])+            {+                case 0x81: // AC-3+                    atype = "AC-3";+                    audio->config.in.codec = HB_ACODEC_AC3;+                    break;+                case 0x82: // HDMV DTS+                case 0x8a: // DTS+                    atype = "DTS";+                    audio->config.in.codec = HB_ACODEC_DCA;+                    break;+                case 0x83: // LPCM+                    atype = "PCM";+                    audio->config.in.codec = HB_ACODEC_LPCM;+                    break;+            }+            audio->id = 0x80bd | (aud_pid_index << 8);+            stream->ts_streamid[1 + aud_pid_index] = 0xbd;+            hb_log("transport stream pid 0x%x (type 0x%x) is %s audio id 0x%x",+                   stream->ts_audio_pids[aud_pid_index],+                   stream->ts_stream_type[1 + aud_pid_index], atype, audio->id);+        }         else if ((buf[3] & 0xe0) == 0xc0)         {             audio->id = buf[3] | aud_pid_index;             audio->config.in.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[1 + aud_pid_index],+                   stream->ts_stream_type[1 + aud_pid_index],                    audio->id);-            stream->ts_audio_stream_type[1 + aud_pid_index] = 0x03;+            stream->ts_stream_type[1 + aud_pid_index] = 0x03;             stream->ts_streamid[1 + aud_pid_index] = buf[3];         }     }@@ -824,7 +1056,7 @@     {         hb_log("transport stream pid 0x%x (type 0x%x) isn't audio",                 stream->ts_audio_pids[aud_pid_index],-                stream->ts_audio_stream_type[1 + aud_pid_index]);+                stream->ts_stream_type[1 + aud_pid_index]); 	}     return audio; }@@ -884,7 +1116,7 @@         hb_buffer_t *es;          // 'buf' contains an MPEG2 PACK - get a list of all it's elementary streams-        hb_demux_ps(buf, list, 0);+        hb_demux_ps( buf, list, 0 );          while ( ( es = hb_list_item( list, 0 ) ) )         {@@ -930,54 +1162,53 @@         stream-> ts_audio_pids[i] = -1;     } +    stream->ts_packet = malloc( stream->packetsize );+ 	// Find the audio and video pids in the stream 	hb_ts_stream_find_pids(stream); -    stream->ts_streamid[0] = 0xE0;		// stream 0 must be video- 	for (i = 0; i < stream->ts_number_video_pids + stream->ts_number_audio_pids; i++) 	{         // demuxing buffer for TS to PS conversion 		stream->ts_buf[i] = malloc( HB_DVD_READ_BUFFER_SIZE ); 	}++    stream->ts_streamid[0] = 0xE0;		// stream 0 must be video } -// ------------------------------------------------------------------------------------+#define MAX_HOLE 208*80 -static off_t align_to_next_packet(FILE* f)+static off_t align_to_next_packet(hb_stream_t *stream) {-	unsigned char buf[188*20];--	off_t start = ftello(f);+    uint8_t buf[MAX_HOLE]; 	off_t pos = 0;+    off_t start = ftello(stream->file_handle); -	if (fread(buf, 188*20, 1, f) == 1)+    if ( start >= stream->packetsize ) {+        start -= stream->packetsize;+        fseeko(stream->file_handle, start, SEEK_SET);+    }++    if (fread(buf, sizeof(buf), 1, stream->file_handle) == 1) 	{-		int found = 0;-		while (!found && (pos < 188))-		{-			found = 1;-			int i = 0;-			for (i = 0; i < 188*20; i += 188)-			{-				unsigned char c = buf[pos+i];-				// Check sync byte-				if ((c != 0x47) && (c != 0x72) && (c != 0x29))-				{-					// this offset failed, try next-					found = 0;-					pos++;-					break;-				}-			}-		}+        const uint8_t *bp = buf;+        int i;++        for ( i = sizeof(buf); --i >= 0; ++bp )+        {+            if ( have_ts_sync( bp, stream->packetsize ) )+            {+                break;+            }+        }+        if ( i >= 0 )+        {+            pos = ( bp - buf ) - stream->packetsize + 188;+            if ( pos < 0 )+                pos = 0;+        } 	}--	if (pos == 188)-		pos = 0;		// failed to find anything!!!!!?--    fseeko(f, start+pos, SEEK_SET);-+    fseeko(stream->file_handle, start+pos, SEEK_SET); 	return pos; } @@ -1063,70 +1294,53 @@     } } -/*- * Get the name of the stream from the type - thanks to VLC for this.- */-static const char *get_stream_name (unsigned char stream_type)+static const char * stream_type_name (uint8_t stream_type) {     switch( stream_type )     {-    case 0x01:  /* MPEG-1 video */-    case 0x02:  /* MPEG-2 video */-    case 0x80:  /* MPEG-2 MOTO video */-        return("MPEG 1/2 Video");-        break;-    case 0x03:  /* MPEG-1 audio */-    case 0x04:  /* MPEG-2 audio */-        return("MPEG Audio");-        break;-    case 0x11:  /* MPEG4 (audio) */-    case 0x0f:  /* ISO/IEC 13818-7 Audio with ADTS transport syntax */-        return("MPEG-4 Audio");-        break;-    case 0x10:  /* MPEG4 (video) */-        return("MPEG-4 Video");-        break;-    case 0x1B:  /* H264 <- check transport syntax/needed descriptor */-        return("H.264 Video");-        break;+    case 0x01: return("ISO 11172 (MPEG1) Video");+    case 0x02: return("ISO 13818-2 (MPEG2) Video");+    case 0x03: return("ISO 11172 (MPEG1) Audio");+    case 0x04: return("ISO 13818-3 (MPEG2) Audio");+    case 0x05: return("ISO 13818-1 private section");+    case 0x06: return("ISO 13818-1 PES private data");+    case 0x07: return("ISO 13522 MHEG");+    case 0x08: return("ISO 13818-1 DSM-CC");+    case 0x09: return("ISO 13818-1 auxiliary");+    case 0x0a: return("ISO 13818-6 multi-protocol encap");+    case 0x0b: return("ISO 13818-6 DSM-CC U-N msgs");+    case 0x0c: return("ISO 13818-6 Stream descriptors");+    case 0x0d: return("ISO 13818-6 Sections");+    case 0x0e: return("ISO 13818-1 auxiliary");+    case 0x0f: return("ISO 13818-7 AAC Audio");+    case 0x10: return("MPEG4 Video");+    case 0x11: return("MPEG4 Audio");+    case 0x12: return("MPEG4 generic");++    case 0x14: return("ISO 13818-6 DSM-CC download");++    case 0x1b: return("H.264 Video");++    case 0x80: return("DigiCipher II Video");+    case 0x81: return("A52/AC-3 Audio");+    case 0x82: return("HDMV DTS Audio");+    case 0x83: return("LPCM Audio");+    case 0x84: return("SDDS Audio");+    case 0x85: return("ATSC Program ID");+    case 0x86: return("SCTE 35 splice info");+    case 0x87: return("ATSC E-AC-3");++    case 0x8a: return("DTS Audio");++    case 0x91: return("A52b/AC-3 Audio");+    case 0x92: return("Subtitle");++    case 0x94: return("SDDS Audio");+    case 0xa0: return("MSCODEC Video");         -    case 0x81:  /* A52 (audio) */-        return("A52/AC-3 Audio");-        break;-    case 0x82:  /* DVD_SPU (sub) */-        return("Subtitle");-        break;-    case 0x83:  /* LPCM (audio) */-        return("LPCM Audio");-        break;-    case 0x84:  /* SDDS (audio) */-        return("SDDS Audio");-        break;-    case 0x85:  /* DTS (audio) */-        return("DTS Audio");-        break;-        -    case 0x91:  /* A52 vls (audio) */-        return("A52b/AC-3 Audio");-        break;-    case 0x92:  /* DVD_SPU vls (sub) */-        return("Subtitle");-        break;-        -    case 0x94:  /* SDDS (audio) */-        return("SDDS Audio");-        break;-        -    case 0xa0:  /* MSCODEC vlc (video) (fixed later) */-        return("MSCODEC Video");-        break;-        -    case 0x06:  /* PES_PRIVATE  (fixed later) */-    case 0x12:  /* MPEG-4 generic (sub/scene/...) (fixed later) */-    case 0xEA:  /* Privately managed ES (VC-1) (fixed later */-    default:-        return("Other");-        break;+    case 0xea: return("VC-1 Video");++    default:   return("Unknown");     } } @@ -1164,64 +1378,63 @@ 	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(&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);+    {+        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(&bb, 8);-	  }+        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(&bb, 8);+        }  -	  if (stream_type == 0x02 || stream_type == 0x10 || stream_type == 0x1B)-	  {-              /* MPEG-2/MPEG-4/H.264 */-              if (stream->ts_number_video_pids <= kMaxNumberVideoPIDS)-		  stream->ts_number_video_pids++;-              stream->ts_video_pids[stream->ts_number_video_pids-1] = elementary_PID;-              stream->ts_video_stream_type[stream->ts_number_video_pids-1] = stream_type;-	  }-          else-          {-              // Defined audio stream types are 0x81 for AC-3/A52 audio and 0x03-              // for mpeg audio. But content producers seem to use other-              // values (0x04 and 0x06 have both been observed) so at this point-              // we say everything that isn't a video pid is audio then at the end-              // of hb_stream_title_scan we'll figure out which are really audio-              // by looking at the PES headers.-              i = stream->ts_number_audio_pids;-              if (i < kMaxNumberAudioPIDS)-                  stream->ts_number_audio_pids++;-              stream->ts_audio_pids[i] = elementary_PID;-              stream->ts_audio_stream_type[1 + i] = stream_type;-              -              if (ES_info_length > 0)-              {-                  decode_element_descriptors(stream, i, ES_info_buf, ES_info_length);-              }-	  }-          -	  cur_pos += 5 /* stream header */ + ES_info_length;+        if (stream->ts_number_video_pids == 0 &&+            ( stream_type == 0x02 || stream_type == 0x10 || stream_type == 0x1B ) )+        {+            stream->ts_video_pids[0] = elementary_PID;+            stream->ts_stream_type[0] = stream_type;+            stream->ts_number_video_pids = 1;+        }+        else+        {+            // Defined audio stream types are 0x81 for AC-3/A52 audio and 0x03+            // for mpeg audio. But content producers seem to use other+            // values (0x04 and 0x06 have both been observed) so at this point+            // we say everything that isn't a video pid is audio then at the end+            // of hb_stream_title_scan we'll figure out which are really audio+            // by looking at the PES headers.+            i = stream->ts_number_audio_pids;+            if (i < kMaxNumberAudioPIDS)+            {+                stream->ts_audio_pids[i] = elementary_PID;+                stream->ts_stream_type[1 + i] = stream_type;+                if (ES_info_length > 0)+                {+                    decode_element_descriptors(stream, i, ES_info_buf,+                                               ES_info_length);+                }+                ++stream->ts_number_audio_pids;+            }+        } -	  free(ES_info_buf);+        cur_pos += 5 /* stream header */ + ES_info_length; -	  if (cur_pos >= section_length - 4 /* stop before the CRC */)-		done_reading_stream_types = 1;-	}+        free(ES_info_buf); +        if (cur_pos >= section_length - 4 /* stop before the CRC */)+        done_reading_stream_types = 1;+    }+ 	free(descriptor_buf); 	return 1; } -// --------------------------------------------------------------------------------------int build_program_map(unsigned char *buf, hb_stream_t *stream)+static int build_program_map(const uint8_t *buf, hb_stream_t *stream) {     // Get adaption header info     int adapt_len = 0;@@ -1283,7 +1496,7 @@     return 0; } -int decode_PAT(unsigned char *buf, hb_stream_t *stream)+static int decode_PAT(const uint8_t *buf, hb_stream_t *stream) {     unsigned char tablebuf[1024];     unsigned int tablepos = 0;@@ -1395,49 +1608,21 @@  static void hb_ts_stream_find_pids(hb_stream_t *stream) {-	unsigned char buf[188];- 	// align to first packet-	align_to_next_packet(stream->file_handle);+    align_to_next_packet(stream);  	// Read the Transport Stream Packets (188 bytes each) looking at first for PID 0 (the PAT PID), then decode that 	// to find the program map PID and then decode that to get the list of audio and video PIDs -	int bytesReadInPacket = 0; 	for (;;) 	{-		// Try to read packet..-		int bytesRead;-		if ((bytesRead = fread(buf+bytesReadInPacket, 1, 188-bytesReadInPacket, stream->file_handle)) != 188-bytesReadInPacket)-		{-			if (bytesRead < 0)-				bytesRead = 0;-			bytesReadInPacket += bytesRead;-+        const uint8_t *buf = next_packet( stream );+        if ( buf == NULL )+        { 			hb_log("hb_ts_stream_find_pids - end of file"); 			break; 		}-		else-		{-			bytesReadInPacket = 0;-		} -		// Check sync byte-		if ((buf[0] != 0x47) && (buf[0] != 0x72) && (buf[0] != 0x29))-		{-            off_t pos = ftello(stream->file_handle) - 188;-            off_t pos2 = align_to_next_packet(stream->file_handle);-            if ( pos2 == 0 )-            {-                hb_log( "hb_ts_stream_find_pids: eof while re-establishing sync @ %lld",-                        pos );-                break;-            }-            hb_log("hb_ts_stream_decode: sync lost @%lld, regained after %lld bytes",-                    pos, pos2 );-			continue;-		}- 		// Get pid 		int pid = (((buf[1] & 0x1F) << 8) | buf[2]) & 0x1FFF; @@ -1474,21 +1659,21 @@  	hb_log("hb_ts_stream_find_pids - found the following PIDS"); 	hb_log("    Video PIDS : ");-	int i=0;+    int i; 	for (i=0; i < stream->ts_number_video_pids; i++) 	{-		hb_log("      0x%x (%d) [Type %s (0x%x)]", -                       stream->ts_video_pids[i], stream->ts_video_pids[i],-                       get_stream_name(stream->ts_video_stream_type[i]),-                       stream->ts_video_stream_type[i]);+        hb_log( "      0x%x type %s (0x%x)", +                stream->ts_video_pids[i],+                stream_type_name(stream->ts_stream_type[i]),+                stream->ts_stream_type[i]); 	} 	hb_log("    Audio PIDS : "); 	for (i = 0; i < stream->ts_number_audio_pids; i++) 	{-		hb_log("      0x%x (%d) [Type %s (0x%x)]", -                       stream->ts_audio_pids[i], stream->ts_audio_pids[i],-                       get_stream_name(stream->ts_audio_stream_type[i]),-                       stream->ts_audio_stream_type[i] );+        hb_log( "      0x%x type %s (0x%x)", +                stream->ts_audio_pids[i],+                stream_type_name(stream->ts_stream_type[i+1]),+                stream->ts_stream_type[i+1] ); 	}  } @@ -1582,7 +1767,7 @@     // we always ship a PACK header plus all the data in our demux buf.     // AC3 audio also always needs it substream header.     len = 14 + stream->ts_pos[curstream];-    if ( stream->ts_audio_stream_type[curstream] == 0x81)+    if ( stream->ts_stream_type[curstream] == 0x81)     {         len += 4;     }@@ -1623,7 +1808,7 @@         tdat[3] = stream->ts_streamid[curstream];          uint16_t plen = stream->ts_pos[curstream] - 6;-        if ( stream->ts_audio_stream_type[curstream] == 0x81)+        if ( stream->ts_stream_type[curstream] == 0x81)         {             // We have to add an AC3 header in front of the data. Add its             // size to the PES packet length.@@ -1659,7 +1844,7 @@     {         // data without a PES start header needs a simple 'continuation'         // PES header. AC3 audio also needs its substream header.-        if ( stream->ts_audio_stream_type[curstream] != 0x81)+        if ( stream->ts_stream_type[curstream] != 0x81)         {             make_pes_header(stream, stream->ts_pos[curstream],                             stream->ts_streamid[curstream]);@@ -1691,53 +1876,6 @@     stream->ts_pos[curstream] = 0; } -static void ts_warn_helper( hb_stream_t *stream, char *log, va_list args )-{-    // limit error printing to at most one per minute of video (at 30fps)-    ++stream->errors;-    if ( stream->frames - stream->last_error_frame >= 30*60 )-    {-        char msg[256];--        vsnprintf( msg, sizeof(msg), log, args );--        if ( stream->errors - stream->last_error_count < 10 )-        {-            hb_log( "stream: error near frame %d: %s", stream->frames, msg );-        }-        else-        {-            int Edelta = stream->errors - stream->last_error_count;-            double Epcnt = (double)Edelta * 100. /-                            (stream->frames - stream->last_error_frame);-            hb_log( "stream: %d new errors (%.0f%%) up to frame %d: %s",-                    Edelta, Epcnt, stream->frames, msg );-        }-        stream->last_error_frame = stream->frames;-        stream->last_error_count = stream->errors;-    }-}--static void ts_warn( hb_stream_t *stream, char *log, ... )-{-    va_list     args;-    va_start( args, log );-    ts_warn_helper( stream, log, args );-    va_end( args );-}--static void ts_err( hb_stream_t *stream, int curstream, char *log, ... )-{-    va_list     args;-    va_start( args, log );-    ts_warn_helper( stream, log, args );-    va_end( args );--    stream->ts_skipbad[curstream] = 1;-    stream->ts_pos[curstream] = 0;-    stream->ts_streamcont[curstream] = -1;-}- static int isIframe( const uint8_t *buf, int adapt_len ) {     // Look for the Group of Pictures packet@@ -1778,10 +1916,6 @@  **********************************************************************/ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf ) {-    int64_t pcr = stream->ts_lastpcr;-	int curstream;-	uint8_t buf[188];-     /*      * stash the output buffer pointer in our stream so we don't have to      * pass it & its original value to everything we call.@@ -1792,8 +1926,12 @@ 	// spin until we get a packet of data from some stream or hit eof 	while ( 1 ) 	{-        if ((fread(buf, 188, 1, stream->file_handle)) != 1)-		{+        int64_t pcr = stream->ts_lastpcr;+        int curstream;++        const uint8_t *buf = next_packet(stream);+        if ( buf == NULL )+        {             // end of file - we didn't finish filling our ps write buffer             // so just discard the remainder (the partial buffer is useless)             hb_log("hb_ts_stream_decode - eof");@@ -1802,24 +1940,6 @@          /* This next section validates the packet */ -		// Check sync byte-		if ((buf[0] != 0x47) && (buf[0] != 0x72) && (buf[0] != 0x29))-		{-            // lost sync - back up to where we started then try to-            // re-establish sync.-            off_t pos = ftello(stream->file_handle) - 188;-            off_t pos2 = align_to_next_packet(stream->file_handle);-            if ( pos2 == 0 )-            {-                hb_log( "hb_ts_stream_decode: eof while re-establishing sync @ %lld",-                        pos );-                return 0;-            }-            ts_warn( stream, "hb_ts_stream_decode: sync lost @%lld, "-                     "regained after %lld bytes", pos, pos2 );-			continue;-		}- 		// Get pid and use it to find stream state. 		int pid = ((buf[1] & 0x1F) << 8) | buf[2];         if ( ( curstream = index_of_pid( pid, stream ) ) < 0 )@@ -1927,7 +2047,8 @@             {                 if ( !stream->ts_foundfirst[0] )                 {-                    if ( !isIframe( buf, adapt_len ) )+                    if ( stream->ts_stream_type[0] == 2 &&+                         !isIframe( buf, adapt_len ) )                     {                         // didn't find an I frame                         continue;@@ -2008,6 +2129,6 @@     stream->last_error_frame = -10000;     stream->last_error_count = 0; -	align_to_next_packet(stream->file_handle);+    align_to_next_packet(stream); }