+ if( pid->es->fmt.i_codec == VLC_FOURCC( 'a', '5', '2', 'b' ) ||
+ pid->es->fmt.i_codec == VLC_FOURCC( 'd', 't', 's', 'b' ) )
+ {
+ i_skip += 4;
+ }
+ else if( pid->es->fmt.i_codec == VLC_FOURCC( 'l', 'p', 'c', 'b' ) ||
+ pid->es->fmt.i_codec == VLC_FOURCC( 's', 'p', 'u', 'b' ) ||
+ pid->es->fmt.i_codec == VLC_FOURCC( 's', 'd', 'd', 'b' ) )
+ {
+ i_skip += 1;
+ }
+ else if( pid->es->fmt.i_codec == VLC_CODEC_SUBT &&
+ pid->es->p_mpeg4desc )
+ {
+ decoder_config_descriptor_t *dcd = &pid->es->p_mpeg4desc->dec_descr;
+
+ if( dcd->i_decoder_specific_info_len > 2 &&
+ dcd->p_decoder_specific_info[0] == 0x10 &&
+ ( dcd->p_decoder_specific_info[1]&0x10 ) )
+ {
+ /* display length */
+ if( p_pes->i_buffer + 2 <= i_skip )
+ i_length = GetWBE( &p_pes->p_buffer[i_skip] );
+
+ i_skip += 2;
+ }
+ if( p_pes->i_buffer + 2 <= i_skip )
+ i_pes_size = GetWBE( &p_pes->p_buffer[i_skip] );
+ /* */
+ i_skip += 2;
+ }
+#ifdef ZVBI_COMPILED
+ else if( pid->es->fmt.i_codec == VLC_CODEC_TELETEXT )
+ i_skip = 0; /*hack for zvbi support */
+#endif
+ /* skip header */
+ while( p_pes && i_skip > 0 )
+ {
+ if( p_pes->i_buffer <= i_skip )
+ {
+ block_t *p_next = p_pes->p_next;
+
+ i_skip -= p_pes->i_buffer;
+ block_Release( p_pes );
+ p_pes = p_next;
+ }
+ else
+ {
+ p_pes->i_buffer -= i_skip;
+ p_pes->p_buffer += i_skip;
+ break;
+ }
+ }
+
+ /* ISO/IEC 13818-1 2.7.5: if no pts and no dts, then dts == pts */
+ if( i_pts >= 0 && i_dts < 0 )
+ i_dts = i_pts;
+
+ if( p_pes )
+ {
+ block_t *p_block;
+ int i;
+
+ if( i_dts >= 0 )
+ p_pes->i_dts = VLC_TS_0 + i_dts * 100 / 9;
+
+ if( i_pts >= 0 )
+ p_pes->i_pts = VLC_TS_0 + i_pts * 100 / 9;
+
+ p_pes->i_length = i_length * 100 / 9;
+
+ p_block = block_ChainGather( p_pes );
+ if( pid->es->fmt.i_codec == VLC_CODEC_SUBT )
+ {
+ if( i_pes_size > 0 && p_block->i_buffer > i_pes_size )
+ {
+ p_block->i_buffer = i_pes_size;
+ }
+ /* Append a \0 */
+ p_block = block_Realloc( p_block, 0, p_block->i_buffer + 1 );
+ if( !p_block )
+ abort();
+ p_block->p_buffer[p_block->i_buffer -1] = '\0';
+ }
+
+ for( i = 0; i < pid->i_extra_es; i++ )
+ {
+ es_out_Send( p_demux->out, pid->extra_es[i]->id,
+ block_Duplicate( p_block ) );
+ }
+
+ es_out_Send( p_demux->out, pid->es->id, p_block );
+ }
+ else
+ {
+ msg_Warn( p_demux, "empty pes" );
+ }
+}
+
+static block_t* ReadTSPacket( demux_t *p_demux )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ block_t *p_pkt;
+
+ /* Get a new TS packet */
+ if( !( p_pkt = stream_Block( p_demux->s, p_sys->i_packet_size ) ) )
+ {
+ msg_Dbg( p_demux, "eof ?" );
+ return NULL;
+ }
+
+ /* Check sync byte and re-sync if needed */
+ if( p_pkt->p_buffer[0] != 0x47 )
+ {
+ msg_Warn( p_demux, "lost synchro" );
+ block_Release( p_pkt );
+ while( vlc_object_alive (p_demux) )
+ {
+ const uint8_t *p_peek;
+ int i_peek, i_skip = 0;
+
+ i_peek = stream_Peek( p_demux->s, &p_peek,
+ p_sys->i_packet_size * 10 );
+ if( i_peek < p_sys->i_packet_size + 1 )
+ {
+ msg_Dbg( p_demux, "eof ?" );
+ return NULL;
+ }
+
+ while( i_skip < i_peek - p_sys->i_packet_size )
+ {
+ if( p_peek[i_skip] == 0x47 &&
+ p_peek[i_skip + p_sys->i_packet_size] == 0x47 )
+ {
+ break;
+ }
+ i_skip++;
+ }
+ msg_Dbg( p_demux, "skipping %d bytes of garbage", i_skip );
+ stream_Read( p_demux->s, NULL, i_skip );
+
+ if( i_skip < i_peek - p_sys->i_packet_size )
+ {
+ break;
+ }
+ }
+ if( !( p_pkt = stream_Block( p_demux->s, p_sys->i_packet_size ) ) )
+ {
+ msg_Dbg( p_demux, "eof ?" );
+ return NULL;
+ }
+ }
+ return p_pkt;
+}
+
+static mtime_t AdjustPCRWrapAround( demux_t *p_demux, mtime_t i_pcr )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+ /*
+ * PCR is 33bit. If PCR reaches to 0x1FFFFFFFF (26:30:43.717), ressets from 0.
+ * So, need to add 0x1FFFFFFFF, for calculating duration or current position.
+ */
+ mtime_t i_adjust = 0;
+ int64_t i_pos = stream_Tell( p_demux->s );
+ int i;
+ for( i = 1; i < p_sys->i_pcrs_num && p_sys->p_pos[i] <= i_pos; ++i )
+ {
+ if( p_sys->p_pcrs[i-1] > p_sys->p_pcrs[i] )
+ i_adjust += 0x1FFFFFFFF;
+ }
+ if( p_sys->p_pcrs[i-1] > i_pcr )
+ i_adjust += 0x1FFFFFFFF;
+
+ return i_pcr + i_adjust;
+}
+
+static mtime_t GetPCR( block_t *p_pkt )
+{
+ const uint8_t *p = p_pkt->p_buffer;
+
+ mtime_t i_pcr = -1;
+
+ if( ( p[3]&0x20 ) && /* adaptation */
+ ( p[5]&0x10 ) &&
+ ( p[4] >= 7 ) )
+ {
+ /* PCR is 33 bits */
+ i_pcr = ( (mtime_t)p[6] << 25 ) |
+ ( (mtime_t)p[7] << 17 ) |
+ ( (mtime_t)p[8] << 9 ) |
+ ( (mtime_t)p[9] << 1 ) |
+ ( (mtime_t)p[10] >> 7 );
+ }
+ return i_pcr;
+}
+
+static int SeekToPCR( demux_t *p_demux, int64_t i_pos )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ mtime_t i_pcr = -1;
+ int64_t i_initial_pos = stream_Tell( p_demux->s );
+
+ if( i_pos < 0 )
+ return VLC_EGENERIC;
+
+ int64_t i_last_pos = i_pos + p_sys->i_packet_size * 4500; //XXX
+ if( i_last_pos > stream_Size( p_demux->s ) - p_sys->i_packet_size )