changeset 10686:8eb690f0e342

- seek() is always synchronized to keyframes, so the decoders don't crash anymore; successfully tested with libmpeg2 and ffmpeg12 - support for tables PAT and PMT, used the associate pids to program and to play the right streams - option -tsprog <number> to specify the chosen program (-vid and -aid still override the single stream pids) - initial support for MPEG4 in TS (M4V is working, but not AAC yet) - defragmenting mechanism (without buffering, so it has 0 added cost) to improve the playback of high bitrate movies - refers to demux_mpg_control() to get length and percentage position in the stream patch by Nico <nsabbi@libero.it>
author arpi
date Sun, 24 Aug 2003 18:07:00 +0000
parents f54ffeb29447
children f8d6f7d59ceb
files libmpdemux/demux_ts.c
diffstat 1 files changed, 1010 insertions(+), 189 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/demux_ts.c	Sun Aug 24 12:34:42 2003 +0000
+++ b/libmpdemux/demux_ts.c	Sun Aug 24 18:07:00 2003 +0000
@@ -42,20 +42,23 @@
 
 #define MAX_HEADER_SIZE 6			/* enough for PES header + length */
 #define MAX_CHECK_SIZE	65535
-#define MAX_PROBE_SIZE	1000000
+#define MAX_PROBE_SIZE	2000000
 #define NUM_CONSECUTIVE_TS_PACKETS 32
 #define NUM_CONSECUTIVE_AUDIO_PACKETS 348
 
 
-int ts_fastparse = 0;
+int ts_prog;
 
 typedef enum
 {
 	UNKNOWN		= -1,
+	VIDEO_MPEG1 	= 0x10000001,
 	VIDEO_MPEG2 	= 0x10000002,
+	VIDEO_MPEG4 	= 0x10000004,
 	AUDIO_MP2   	= 0x50,
 	AUDIO_A52   	= 0x2000,
-	AUDIO_LPCM_BE  	= 0x10001
+	AUDIO_LPCM_BE  	= 0x10001,
+	AUDIO_AAC	= (('A' << 24) | ('4' << 16) | ('P' << 8) | 'M')
 	/*,
 	SPU_DVD		= 0x3000000,
 	SPU_DVB		= 0x3000001,
@@ -81,7 +84,65 @@
 
 
 typedef struct {
+	demux_stream_t *ds;
+	demux_packet_t *pack;
+	int offset, buffer_size;
+	int broken; //set if it's the final part of a chunk (doesn't have a corresponding is_start)
+} av_fifo_t;
+
+typedef struct {
+	uint8_t skip;
+	uint8_t table_id;
+	uint8_t ssi;
+	uint16_t section_length;
+	uint16_t ts_id;
+	uint8_t version_number;
+	uint8_t curr_next;
+	uint8_t section_number;
+	uint8_t last_section_number;
+	struct pat_progs_t {
+		uint16_t id;
+		uint16_t pmt_pid;
+	} *progs;
+	uint16_t progs_cnt;
+	char buffer[65535];
+	uint8_t buffer_len;
+	} pat_t;
+
+typedef struct {
+	uint16_t progid;
+	uint8_t skip;
+	uint8_t table_id;
+	uint8_t ssi;
+	uint16_t section_length;
+	uint8_t version_number;
+	uint8_t curr_next;
+	uint8_t section_number;
+	uint8_t last_section_number;
+	uint16_t PCR_PID;
+	uint16_t prog_descr_length;
+	char buffer[2048];
+	uint8_t buffer_len;
+	uint16_t es_cnt;
+	struct pmt_es_t {
+		uint16_t pid;
+		uint32_t type;	//it's 8 bit long, but cast to the right type as FOURCC
+		uint16_t descr_length;
+	} *es;
+} pmt_t;
+
+typedef struct {
 	MpegTSContext ts;
+	int is_synced;	//synced to the beginning of priv->last_pid PES header
+	int last_afc;	//bytes read from the last adaption field
+	int last_pid;
+	int is_start;
+	int eof;
+	av_fifo_t fifo[2];	//0 for audio, 1 for video
+	pat_t pat;
+	pmt_t *pmt;
+	uint16_t pmt_cnt;
+	uint32_t prog;
 } ts_priv_t;
 
 
@@ -121,11 +182,11 @@
 	const int buf_size = (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS);
 	unsigned char buf[buf_size], done = 0, *ptr;
 	uint32_t _read, i, count = 0, is_ts;
-	int cc[NB_PID_MAX], last_cc[NB_PID_MAX], pid, cc_ok, c;
+	int cc[NB_PID_MAX], last_cc[NB_PID_MAX], pid, cc_ok, c, good, bad;
 	uint8_t size = 0;
 	off_t pos = 0;
 
-	mp_msg(MSGT_DEMUX, MSGL_V, "Checking for TS...\n");
+	mp_msg(MSGT_DEMUX, MSGL_V, "Checking for MPEG-TS...\n");
 
 	is_ts = 0;
 	while(! done)
@@ -142,7 +203,7 @@
 
 		if(c != 0x47)
 		{
-			mp_msg(MSGT_DEMUX, MSGL_V, "NOT A TS FILE1\n");
+			mp_msg(MSGT_DEMUX, MSGL_V, "THIS DOESN'T LOOK LIKE AN MPEG-TS FILE!\n");
 			is_ts = 0;
 			done = 1;
 			continue;
@@ -180,6 +241,7 @@
 	  return 0;
 
 	//LET'S CHECK continuity counters
+	good = bad = 0;
 	for(count = 0; count < NB_PID_MAX; count++)
 	{
 		cc[count] = last_cc[count] = -1;
@@ -199,46 +261,173 @@
 		cc_ok = (last_cc[pid] < 0) || ((((last_cc[pid] + 1) & 0x0f) == cc[pid]));
 		mp_msg(MSGT_DEMUX, MSGL_DBG2, "PID %d, COMPARE CC %d AND LAST_CC %d\n", pid, cc[pid], last_cc[pid]);
 		if(! cc_ok)
-			return 0;
+			//return 0;
+			bad++;
+		else
+			good++;
 
 		last_cc[pid] = cc[pid];
-		done++;
 	}
 
-	return size;
+	mp_msg(MSGT_DEMUX, MSGL_V, "GOOD CC: %d, BAD CC: %d\n", good, bad);
+
+	if(good >= bad)
+		return size;
+	else
+		return 0;
+}
+
+
+static inline int32_t progid_idx_in_pmt(ts_priv_t *priv, uint16_t progid)
+{
+	int x;
+
+	if(priv->pmt == NULL)
+		return -1;
+
+	for(x = 0; x < priv->pmt_cnt; x++)
+	{
+		if(priv->pmt[x].progid == progid)
+			return x;
+	}
+
+	return -1;
 }
 
 
+static inline int32_t progid_for_pid(ts_priv_t *priv, int pid, int32_t req)		//finds the first program listing a pid
+{
+	int i, j;
+	pmt_t *pmt;
+
+
+	if(priv->pmt == NULL)
+		return -1;
 
 
-static void ts_detect_streams(demuxer_t *demuxer, uint32_t *a,  uint32_t *v, int *fapid, int *fvpid)
+	for(i=0; i < priv->pmt_cnt; i++)
+	{
+		pmt = &(priv->pmt[i]);
+
+		if(pmt->es == NULL)
+			return -1;
+
+		for(j = 0; j < pmt->es_cnt; j++)
+		{
+			if(pmt->es[j].pid == pid)
+			{
+				if((req == 0) || (req == pmt->progid))
+					return pmt->progid;
+			}
+		}
+
+	}
+	return -1;
+}
+
+
+static void ts_detect_streams(demuxer_t *demuxer, uint32_t *a,  uint32_t *v, int *fapid, int *fvpid, int32_t *prog)
 {
-	int video_found = 0, audio_found = 0, i, num_packets = 0;
+	int video_found = 0, audio_found = 0, i, num_packets = 0, req_apid, req_vpid;
+	int is_audio, is_video, has_tables;
+	int32_t p, chosen_pid;
 	off_t pos=0;
 	ES_stream_t es;
 	unsigned char tmp[TS_FEC_PACKET_SIZE];
 	ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
 
+	priv->is_synced = 0;
+	priv->last_afc = 0;
+	priv->last_pid = 8192;		//invalid pid
+	priv->is_start = 0;
+	priv->eof = 0;
 
-	mp_msg(MSGT_DEMUXER, MSGL_INFO, "PROBING UP TO %u\n", MAX_PROBE_SIZE);
+	req_apid = *fapid;
+	req_vpid = *fvpid;
+
+	has_tables = 0;
+	mp_msg(MSGT_DEMUXER, MSGL_INFO, "PROBING UP TO %u, PROG: %d\n", MAX_PROBE_SIZE, *prog);
 	while(pos <= MAX_PROBE_SIZE)
 	{
+		pos = stream_tell(demuxer->stream);
 		if(ts_parse(demuxer, &es, tmp, 1))
 		{
-			mp_msg(MSGT_DEMUXER, MSGL_DBG2, "TYPE: %x, PID: %d\n", es.type, es.pid);
+			is_audio = ((es.type == AUDIO_MP2) || (es.type == AUDIO_A52) || (es.type == AUDIO_LPCM_BE) || (es.type == AUDIO_AAC));
+			is_video = ((es.type == VIDEO_MPEG1) || (es.type == VIDEO_MPEG2) || (es.type == VIDEO_MPEG4));
+
+			if((! is_audio) && (! is_video))
+				continue;
+
+			if(is_video)
+			{
+    				chosen_pid = (req_vpid == es.pid);
+				if((! chosen_pid) && (req_vpid > 0))
+					continue;
+			}
+			else if(is_audio)
+			{
+				chosen_pid = (req_apid == es.pid);
+				if((! chosen_pid) && (req_apid > 0))
+					continue;
+			}
+
+			if(req_vpid < 0 && req_apid < 0)
+				chosen_pid = 1;
+
+			p = progid_for_pid(priv, es.pid, *prog);
+			if(p != -1)
+				has_tables++;
+
+			if((*prog == 0) && (p != -1))
+			{
+				if(chosen_pid)
+					*prog = p;
+			}
+
+			if((*prog > 0) && (*prog != p))
+			{
+				if(audio_found)
+				{
+					if(is_video && (req_vpid == es.pid))
+					{
+						*v = es.type;
+						*fvpid = es.pid;
+						video_found = 1;
+						break;
+					}
+				}
+
+				if(video_found)
+				{
+					if(is_audio && (req_apid == es.pid))
+					{
+						*a = es.type;
+						*fapid = es.pid;
+						audio_found = 1;
+						break;
+					}
+				}
 
 
-			if((*fvpid == -1) || (*fvpid == es.pid))
+				continue;
+			}
+
+
+			mp_msg(MSGT_DEMUXER, MSGL_DBG2, "TYPE: %x, PID: %d, PROG FOUND: %d\n", es.type, es.pid, *prog);
+
+
+			if(is_video)
 			{
-				if(es.type == VIDEO_MPEG2)
+				if((req_vpid == -1) || (req_vpid == es.pid))
 				{
-					*v = VIDEO_MPEG2;
+					*v = es.type;
 					*fvpid = es.pid;
 					video_found = 1;
 				}
 			}
 
-			if(((*fvpid == -2) || (num_packets >= NUM_CONSECUTIVE_AUDIO_PACKETS)) && audio_found)
+
+			if(((req_vpid == -2) || (num_packets >= NUM_CONSECUTIVE_AUDIO_PACKETS)) && audio_found)
 			{
 				//novideo or we have at least 348 audio packets (64 KB) without video (TS with audio only)
 				*v = 0;
@@ -246,65 +435,54 @@
 			}
 
 
-			if((*fapid == -1) || (*fapid == es.pid))
+			if(is_audio)
 			{
-				if(es.type == AUDIO_MP2)
+				if((req_apid == -1) || (req_apid == es.pid))
 				{
-					*a = AUDIO_MP2;	//MPEG1L2 audio
-					*fapid = es.pid;
-					audio_found = 1;
-				}
-
-				if(es.type == AUDIO_A52)
-				{
-					*a = AUDIO_A52;	//A52 audio
-					*fapid = es.pid;
-					audio_found = 1;
-				}
-
-				if(es.type == AUDIO_LPCM_BE)		//LPCM AUDIO
-				{
-					*a = AUDIO_LPCM_BE;
+					*a = es.type;
 					*fapid = es.pid;
 					audio_found = 1;
 				}
 			}
 
 			if(audio_found && (*fapid == es.pid) && (! video_found))
-			  num_packets++;
+				num_packets++;
 
-			if((*fapid == -2) && video_found)
+			if((req_apid == -2) && video_found)
 			{
 				*a = 0;
 				break;
 			}
 
-			pos = stream_tell(demuxer->stream);
-			if(video_found && audio_found)
-			break;
+			if((has_tables==0) && (video_found && audio_found) && (pos >= 1000000))
+				break;
 		}
 	}
 
 	if(video_found)
-	    mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG2(pid=%d)...", *fvpid);
+		mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG%d(pid=%d)...", (*v == VIDEO_MPEG1 ? 1 : (*v == VIDEO_MPEG2 ? 2 : 4)), *fvpid);
 	else
 	{
 	    //WE DIDN'T MATCH ANY VIDEO STREAM
-	    mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO!\n");
+	    mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO! ");
 	}
 
 	if(*a == AUDIO_MP2)
-		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MP2(pid=%d)\n", *fapid);
+		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MP2(pid=%d)", *fapid);
 	else if(*a == AUDIO_A52)
-		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52(pid=%d)\n", *fapid);
+		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52(pid=%d)", *fapid);
 	else if(*a == AUDIO_LPCM_BE)
-		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO LPCM(pid=%d)\n", *fapid);
+		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO LPCM(pid=%d)", *fapid);
+	else if(*a == AUDIO_AAC)
+		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO AAC(pid=%d)", *fapid);
 	else
 	{
 		//WE DIDN'T MATCH ANY AUDIO STREAM, SO WE FORCE THE DEMUXER TO IGNORE AUDIO
-		mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO AUDIO!\n");
+		mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO AUDIO! ");
 	}
 
+	mp_msg(MSGT_DEMUXER, MSGL_INFO, " PROGRAM N. %d\n", *prog);
+
 	for(i=0; i<8192; i++)
 	{
 		if(priv->ts.pids[i] != NULL)
@@ -326,6 +504,7 @@
 	sh_audio_t *sh_audio;
 	uint32_t at = 0, vt = 0;
 	ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
+	demuxer_t *od;
 
 	mp_msg(MSGT_DEMUX, MSGL_DBG2, "DEMUX OPEN, AUDIO_ID: %d, VIDEO_ID: %d, SUBTITLE_ID: %d,\n",
 		demuxer->audio->id, demuxer->video->id, demuxer->sub->id);
@@ -333,6 +512,7 @@
 
 	demuxer->type= DEMUXER_TYPE_MPEG_TS;
 
+
 	stream_reset(demuxer->stream);
 	stream_seek(demuxer->stream, 0);
 
@@ -341,30 +521,46 @@
 	    return NULL;
 
 	priv = malloc(sizeof(ts_priv_t));
+	if(priv == NULL)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_FATAL, "DEMUX_OPEN_TS, couldn't allocate %lu bytes, exit\n",
+			sizeof(ts_priv_t));
+		return NULL;
+	}
 
 	for(i=0; i < 8192; i++)
 	    priv->ts.pids[i] = NULL;
+	priv->pat.progs = NULL;
+	priv->pat.progs_cnt = 0;
+
+	priv->pmt = NULL;
+	priv->pmt_cnt = 0;
+
 	priv->ts.packet_size = packet_size;
 
 
 	demuxer->priv = priv;
-
-	if(demuxer->stream->type != STREAMTYPE_FILE) demuxer->seekable=0;
-	else demuxer->seekable = 1;
+	if(demuxer->stream->type != STREAMTYPE_FILE)
+		demuxer->seekable = 0;
+	else
+		demuxer->seekable = 1;
 
-
-	ts_detect_streams(demuxer, &at, &vt, &demuxer->audio->id, &demuxer->video->id);
-	mp_msg(MSGT_DEMUXER,MSGL_INFO, "Opened TS demuxer2, audio: %x(pid %d), video: %x(pid %d)...\n", at, demuxer->audio->id, vt, demuxer->video->id);
+	stream_seek(demuxer->stream, 0);	//IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES?
+	ts_detect_streams(demuxer, &at, &vt, &demuxer->audio->id, &demuxer->video->id, &ts_prog);
+	mp_msg(MSGT_DEMUXER,MSGL_INFO, "Opened TS demuxer, audio: %x(pid %d), video: %x(pid %d)...\n", at, demuxer->audio->id, vt, demuxer->video->id);
 
 
 	if(vt)
 	{
+		if(vt == VIDEO_MPEG4)
+			demuxer->file_format= DEMUXER_TYPE_MPEG4_IN_TS;
+
 		sh_video = new_sh_video(demuxer, 0);
 		sh_video->ds = demuxer->video;
 		sh_video->format = vt;
 		demuxer->video->sh = sh_video;
 
-		mp_msg(MSGT_DEMUXER,MSGL_INFO, "OPENED_SH_VIDEO, VD: %x\n");
+		mp_msg(MSGT_DEMUXER,MSGL_INFO, "OPENED_SH_VIDEO\n");
 	}
 
 	if(at)
@@ -378,14 +574,38 @@
 	}
 
 
-	mp_msg(MSGT_DEMUXER,MSGL_INFO, "Opened TS demuxer...");
+	mp_msg(MSGT_DEMUXER,MSGL_INFO, "Opened TS demuxer2\n");
+
+	/*
+	demuxer->movi_start = 0;
+	demuxer->movi_end = demuxer->stream->end_pos;
+	*/
+
+	stream_seek(demuxer->stream, 0);	//IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES?
+
 
 
-	demuxer->movi_start = 0;
-	demuxer->movi_end = demuxer->stream->end_pos;
+	priv->is_synced = 0;
+	priv->last_afc = 0;
+	priv->last_pid = 8192;		//invalid pid
+	priv->is_start = 0;
 
-	stream_seek(demuxer->stream, 0);		//IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES?
+	for(i=0; i< 2; i++)
+	{
+		priv->fifo[i].pack  = NULL;
+		priv->fifo[i].offset = 0;
+		priv->fifo[i].broken = 1;
+	}
+	priv->fifo[0].ds = demuxer->audio;
+	priv->fifo[1].ds = demuxer->video;
 
+	priv->fifo[0].buffer_size = 1536;
+	priv->fifo[1].buffer_size = 32767;
+	priv->eof = 0;
+
+	priv->pat.buffer_len = 0;
+
+	demuxer->filepos = stream_tell(demuxer->stream);
 	return demuxer;
 }
 
@@ -407,15 +627,18 @@
 
 
 
-static int pes_parse2(unsigned char *buf, uint16_t packet_len, ES_stream_t *es)
+static int pes_parse2(unsigned char *buf, uint16_t packet_len, ES_stream_t *es, int32_t type_from_pmt)
 {
 	unsigned char  *p;
 	uint32_t       header_len;
-	int64_t        pts, escr, dts;
+	int64_t        pts;
 	uint32_t       stream_id;
-	uint32_t       pkt_len, es_rate;
-	//NEXT might be needed:
+	uint32_t       pkt_len;
+
+	//THE FOLLOWING CODE might be needed in the future:
 	//uint8_t        es_rate_flag, escr_flag, pts_flag;
+	//int64_t      escr, dts;
+	//uint32_t es_rate;
 
 	//Here we are always at the start of a PES packet
 	mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(%X, %d): \n", buf, packet_len);
@@ -496,7 +719,7 @@
 
 	header_len = p[8];
 
-	/* sometimes corruption on header_len causes segfault in memcpy below */
+
 	if (header_len + 9 > pkt_len) //9 are the bytes read up to the header_length field
 	{
 		mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_ts: illegal value for PES_header_data_length (0x%02x)\n", header_len);
@@ -509,10 +732,10 @@
 	if(es->payload_size)
 		es->payload_size -= header_len + 3;
 
+
 	if (stream_id == 0xbd)
 	{
-		/* hack : ac3 track */
-		int track, spu_id;
+		int track; //, spu_id;
 
 		mp_msg(MSGT_DEMUX, MSGL_DBG3, "pes_parse2: audio buf = %02X %02X %02X %02X %02X %02X %02X %02X, 80: %d\n",
 			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[0] & 0x80);
@@ -526,10 +749,14 @@
 		* do not include any of the ac3 header info in their audio tracks
 		* these "raw" streams may begin with a byte that looks like a stream type.
 		*/
-		if(	/* ac3 - raw or syncword */
-			(p[0] == 0x0B && p[1] == 0x77))
+
+
+		if(
+			(type_from_pmt == AUDIO_A52) ||		 /* ac3 - raw */
+			(p[0] == 0x0B && p[1] == 0x77)		/* ac3 - syncword */
+		)
 		{
-			mp_msg(MSGT_DEMUX, MSGL_DBG2, "AC3 SYNCWORD\n");
+			mp_msg(MSGT_DEMUX, MSGL_DBG2, "AC3 RAW OR SYNCWORD\n");
 			es->start = p;
 			es->size  = packet_len;
 			es->type  = AUDIO_A52;
@@ -604,6 +831,19 @@
 
 		return es->size;
 	}
+	else if ((stream_id == 0xfa))
+	{
+		if(type_from_pmt != -1)	//MP4 A/V
+		{
+			es->start   = p;
+			es->size    = packet_len;
+			es->type    = type_from_pmt;
+			if(es->payload_size)
+				es->payload_size -= packet_len;
+
+			return es->size;
+		}
+	}
 	else if ((stream_id & 0xe0) == 0xc0)
 	{
 		int track;
@@ -616,6 +856,16 @@
 
 		return es->size;
 	}
+	else if (type_from_pmt != -1)	//as a last resort here we trust the PMT, if present
+	{
+		es->start   = p;
+		es->size    = packet_len;
+		es->type    = type_from_pmt;
+		es->payload_size -= packet_len;
+
+		return es->size;
+	}
+
 	else
 	{
 		mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2: unknown packet, id: %x\n", stream_id);
@@ -642,40 +892,425 @@
 }
 
 
+static void ts_dump_streams(ts_priv_t *priv)
+{
+	int i;
+
+	for(i = 0; i < 2; i++)
+	{
+		if((priv->fifo[i].pack != NULL) && (priv->fifo[i].offset != 0))
+		{
+			resize_demux_packet(priv->fifo[i].pack, priv->fifo[i].offset);
+			ds_add_packet(priv->fifo[i].ds, priv->fifo[i].pack);
+		}
+	}
+
+	priv->eof = 1;
+}
+
+
+static inline int32_t prog_idx_in_pat(ts_priv_t *priv, uint16_t progid)
+{
+	int x;
+
+	if(priv->pat.progs == NULL)
+			return -1;
+
+	for(x = 0; x < priv->pat.progs_cnt; x++)
+	{
+		if(priv->pat.progs[x].id == progid)
+			return x;
+	}
+
+	return -1;
+}
+
+
+static inline int32_t prog_id_in_pat(ts_priv_t *priv, uint16_t pid)
+{
+	int x;
+
+	if(priv->pat.progs == NULL)
+		return -1;
+
+	for(x = 0; x < priv->pat.progs_cnt; x++)
+	{
+		if(priv->pat.progs[x].pmt_pid == pid)
+			return priv->pat.progs[x].id;
+	}
+
+	return -1;
+}
+
+
+static int parse_pat(ts_priv_t * priv, int is_start, unsigned char *buff, int size)
+{
+	uint8_t skip, m = 0;
+	unsigned char *ptr;
+	unsigned char *base; //, *crc;
+	int entries, i, sections;
+	uint16_t progid;
+	//uint32_t o_crc, calc_crc;
+
+	//PRE-FILLING
+	if(! is_start)
+	{
+		if(priv->pat.buffer_len == 0) //a broken packet
+		{
+			return 0;
+		}
+
+		if(priv->pat.skip)
+		    m = min(priv->pat.skip, size);
+
+		priv->pat.skip -= m;
+		if(m == size)
+			return -1;	//keep on buffering
+	}
+	else	//IS_START, replace the old content
+	{
+		priv->pat.buffer_len = 0;
+		skip = buff[0]+1;
+		m = min(skip, size);
+
+		priv->pat.skip = skip - m;
+
+		if(m == size)
+			return -1;
+	}
+
+	//FILLING
+	memcpy(&(priv->pat.buffer[priv->pat.buffer_len]), &buff[m], size - m);
+
+	priv->pat.buffer_len += size - m;
+
+	//PARSING
+	ptr = priv->pat.buffer;
+
+	priv->pat.table_id = ptr[0];
+	priv->pat.ssi = (ptr[1] >> 7) & 0x1;
+	priv->pat.curr_next = ptr[5] & 0x01;
+	priv->pat.ts_id = (ptr[3]  << 8 ) | ptr[4];
+	priv->pat.version_number = (ptr[5] >> 1) & 0x1F;
+	priv->pat.section_length = ((ptr[1] & 0x03) << 8 ) | ptr[2];
+	priv->pat.section_number = ptr[6];
+	priv->pat.last_section_number = ptr[7];
+
+	/*CRC CHECK
+	crc = &(priv->pat.buffer[priv->pat.section_length - 4]);
+	o_crc = (crc[0] << 24) | (crc[1] << 16) | (crc[2] << 8) | crc[3];
+	calc_crc = CalcCRC32(0xFFFFFFFFL, priv->pat.buffer, priv->pat.section_length);
+	printf("CRC ORIGINALE: %x, CALCOLATO: %x\n", o_crc, calc_crc);
+	*/
+
+
+	if((! priv->pat.curr_next) || (priv->pat.table_id != 0)) // || (! priv->pat.ssi))
+		return 0;
+
+
+	//beginning of sections loop
+	sections = priv->pat.last_section_number - priv->pat.section_number + 1;
+	mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PAT, section %d of %d, TOTAL: %d\n", priv->pat.section_number, priv->pat.last_section_number, sections);
+
+	if(priv->pat.section_length + 3 > priv->pat.buffer_len)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PAT, section larger than buffer size: %d > %d, EXIT\n",
+			priv->pat.section_length, priv->pat.buffer_len - 3);
+
+		return -1;	//KEEP ON FILLING THE TABLE
+	}
+
+	entries = (int) (priv->pat.section_length - 9) / 4;	//entries per section
+
+
+	for(i=0; i < entries; i++)
+	{
+		int32_t idx;
+		base = &ptr[8 + i*4];
+		progid = (base[0] << 8) | base[1];
+
+		if((idx = prog_idx_in_pat(priv, progid)) == -1)
+		{
+			int sz = sizeof(struct pat_progs_t) * (priv->pat.progs_cnt+1);
+			priv->pat.progs = (struct pat_progs_t*) realloc(priv->pat.progs, sz);
+			if(priv->pat.progs == NULL)
+			{
+				mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PAT: COULDN'T REALLOC %d bytes, NEXT\n", sz);
+				break;
+			}
+
+			idx = priv->pat.progs_cnt;
+			priv->pat.progs_cnt++;
+		}
+
+		priv->pat.progs[idx].id = progid;
+		priv->pat.progs[idx].pmt_pid = ((base[2]  & 0x1F) << 8) | base[3];
+		mp_msg(MSGT_DEMUX, MSGL_V, "PROG: %d (%d-th of %d), PMT: %d\n", priv->pat.progs[idx].id, i+1, entries, priv->pat.progs[idx].pmt_pid);
+	}
+
+	return 1;
+}
+
+
+static inline int32_t es_pid_in_pmt(pmt_t * pmt, uint16_t pid)
+{
+	int i;
+
+	if(pmt == NULL)
+		return -1;
+
+	if(pmt->es == NULL)
+		return -1;
+
+	for(i = 0; i < pmt->es_cnt; i++)
+	{
+		if(pmt->es[i].pid == pid)
+			return i;
+	}
+
+	return -1;
+}
 
 
 
+static int parse_pmt(ts_priv_t * priv, uint16_t progid, uint16_t pid, int is_start, unsigned char *buff, int size)
+{
+	unsigned char *base, *es_base;
+	pmt_t *pmt;
+	int32_t idx, es_count, section_bytes;
+	uint8_t skip, m=0;
+
+	idx = progid_idx_in_pmt(priv, progid);
+
+	if(idx == -1)
+	{
+		int sz = (priv->pmt_cnt + 1) * sizeof(pmt_t);
+		priv->pmt = (pmt_t *) realloc(priv->pmt, sz);
+		if(priv->pmt == NULL)
+		{
+			mp_msg(MSGT_DEMUX, MSGL_ERR, "FILL_PMT: COULDN'T REALLOC %d bytes, NEXT\n", sz);
+			return NULL;
+		}
+
+		idx = priv->pmt_cnt;
+		memset(&(priv->pmt[idx]), 0, sizeof(pmt_t));
+		priv->pmt_cnt++;
+	}
+
+	pmt = &(priv->pmt[idx]);
+
+
+	if(! is_start)
+	{
+		if(pmt->buffer_len == 0)
+		{
+			//BROKEN PMT PACKET, DISCARD
+			return -1;
+		}
+
+		if(pmt->skip)
+		    m = min(pmt->skip, size);
+
+		pmt->skip -= m;
+		if(m == size)
+			return 0;
+	}
+	else
+	{
+		pmt->buffer_len = 0;
+		skip = buff[0] + 1;
+		m = min(skip, size);
+
+		pmt->skip = skip - m;
+
+		if(m == size)
+			return 0;
+	}
+
+	memcpy(&(pmt->buffer[pmt->buffer_len]), &buff[m], size - m);
+	pmt->progid = progid;
+	pmt->buffer_len += size - m;
+
+
+	mp_msg(MSGT_DEMUX, MSGL_V, "FILL_PMT(prog=%d), PMT_len: %d, IS_START: %d, TSPID: %d\n",
+		progid, pmt->buffer_len, is_start, pid);
+
+	base = pmt->buffer;
+
+
+	pmt->table_id = base[0];
+	pmt->ssi = base[1] & 0x80;
+	pmt->section_length = (((base[1] & 0xf) << 8 ) | base[2]);
+	pmt->version_number = (base[5] >> 1) & 0x1f;
+	pmt->curr_next = (base[5] & 1);
+	pmt->section_number = base[6];
+	pmt->last_section_number = base[7];
+	pmt->PCR_PID = ((base[8] & 0x1f) << 8 ) | base[9];
+	pmt->prog_descr_length = ((base[10] & 0xf) << 8 ) | base[11];
+
+
+
+	if((pmt->curr_next == 0) || (pmt->table_id != 2))
+		return -1;
+
+
+	if(pmt->section_length + 3 > pmt->buffer_len)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, SECTION LENGTH TOO LARGE FOR CURRENT BUFFER (%d vs %d), NEXT TIME\n", pmt->section_length, pmt->buffer_len);
+		return -1;
+	}
+
+	if(pmt->prog_descr_length > pmt->section_length - 9)
+	{
+		mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, INVALID PROG_DESCR LENGTH (%d vs %d)\n", pmt->prog_descr_length, pmt->section_length - 9);
+		return -1;
+	}
+
+
+	es_base = &base[12 + pmt->prog_descr_length];	//the beginning of th ES loop
+
+	section_bytes= pmt->section_length - 13 - pmt->prog_descr_length;
+	es_count  = 0;
+
+	while(section_bytes >= 5)
+	{
+		int es_pid, es_type;
+
+		es_type = es_base[0];
+		es_pid = ((es_base[1] & 0x1f) << 8) | es_base[2];
+
+		idx = es_pid_in_pmt(pmt, es_pid);
+		if(idx == -1)
+		{
+			int sz = sizeof(struct pmt_es_t) * (pmt->es_cnt + 1);
+			pmt->es = (struct pmt_es_t *) realloc(pmt->es, sz);
+			if(pmt->es == NULL)
+			{
+				mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT, COULDN'T ALLOCATE %d bytes for PMT_ES\n", sz);
+				continue;
+			}
+			idx = pmt->es_cnt;
+			pmt->es_cnt++;
+		}
+
+		pmt->es[idx].descr_length = ((es_base[3] & 0xf) << 8) | es_base[4];
+
+
+		if(pmt->es[idx].descr_length > section_bytes - 5)
+		{
+			mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT, ES_DESCR_LENGTH TOO LARGE %d > %d, EXIT %d bytes for PMT_ES\n",
+				pmt->es[idx].descr_length, section_bytes - 5);
+			return -1;
+		}
+
+
+		pmt->es[idx].pid = es_pid;
+		pmt->es[idx].type = es_type;
+
+		switch(es_type)
+		{
+			case 1:
+				pmt->es[idx].type = VIDEO_MPEG1;
+				break;
+			case 2:
+				pmt->es[idx].type = VIDEO_MPEG2;
+				break;
+			case 3:
+			case 4:
+				pmt->es[idx].type = AUDIO_MP2;
+				break;
+			case 6:
+			{
+				int j;
+				for(j = 5; j < pmt->es[idx].descr_length; j += es_base[j+1] + 2)	//possible DVB-AC3
+					if(es_base[j] == 0x6a)
+						pmt->es[idx].type = AUDIO_A52;
+			}
+			break;
+
+			case 0x10:
+				pmt->es[idx].type = VIDEO_MPEG4;
+				break;
+			case 0x11:
+				pmt->es[idx].type = AUDIO_AAC;
+				break;
+
+			case 0x81:
+				pmt->es[idx].type = AUDIO_A52;
+				break;
+		}
+
+
+		section_bytes -= 5 + pmt->es[idx].descr_length;
+		mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT(%d INDEX %d), STREAM: %d, FOUND pid=0x%x (%d), type=0x%x, ES_DESCR_LENGTH: %d, bytes left: %d\n",
+			progid, idx, es_count, pmt->es[idx].pid, pmt->es[idx].pid, pmt->es[idx].type, pmt->es[idx].descr_length, section_bytes);
+
+
+		es_base += 5 + pmt->es[idx].descr_length;
+
+		es_count++;
+	}
+
+	return 1;
+}
+
 
 // 0 = EOF or no stream found
-// 1 = successfully read a packet
+// else = [-] number of bytes written to the packet
 static int ts_parse(demuxer_t *demuxer , ES_stream_t *es, unsigned char *packet, int probe)
 {
 	ES_stream_t *tss;
 	uint8_t done = 0;
 	int buf_size, is_start;
-	int len, pid, last_pid, cc, cc_ok, afc, _read;
+	int len, pid, cc, cc_ok, afc, _read;
 	ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
 	stream_t *stream = demuxer->stream;
 	char *p, tmp[TS_FEC_PACKET_SIZE];
-	demux_stream_t *ds;
-	demux_packet_t *dp;
+	demux_stream_t *ds = NULL;
+	demux_packet_t **dp = NULL;
+	int *dp_offset = 0, *buffer_size = 0, *broken = NULL;
+	int32_t progid, pid_idx, pid_type;
+
+
+	while(! done)
+	{
+		if(stream_eof(stream))
+		{
+			if(! priv->eof)
+			{
+				ts_dump_streams(priv);
+				demuxer->filepos = stream_tell(demuxer->stream);
+				return -1;
+			}
+			else
+				return 0;
+		}
 
 
-	while(! done)	//while pid=last_pid add_to_buffer
-	{
-		if(! ts_sync(stream))
+		if(! priv->is_synced)
 		{
-			mp_msg(MSGT_DEMUX, MSGL_V, "TS_PARSE: COULDN'T SYNC\n");
-			return 0;
-		}
+			if(! ts_sync(stream))
+			{
+				mp_msg(MSGT_DEMUX, MSGL_V, "TS_PARSE: COULDN'T SYNC\n");
+				return 0;
+			}
 
-		len = stream_read(stream, &packet[1], 3);
-		if (len != 3)
-			return 0;
+			len = stream_read(stream, &packet[1], 3);
+			if (len != 3)
+				return 0;
+		}
 		_read = 4;
 
-		is_start = packet[1] & 0x40;
-		pid = ((packet[1] & 0x1f) << 8) | packet[2];
+		if(! priv->is_synced)
+		{
+			is_start = packet[1] & 0x40;
+			pid = ((packet[1] & 0x1f) << 8) | packet[2];
+		}
+		else
+		{
+			is_start = priv->is_start;
+			pid = priv->last_pid;
+		}
 
 		tss = priv->ts.pids[pid];			//an ES stream
 		if(tss == NULL)
@@ -689,11 +1324,14 @@
 			tss->type = UNKNOWN;
 			tss->payload_size = 0;
 			priv->ts.pids[pid] 	= tss;
-			mp_msg(MSGT_DEMUX, MSGL_V, "new TS pid=%u\n", pid);
+			mp_msg(MSGT_DEMUX, MSGL_INFO, "\nNew TS pid=%u\n", pid);
 		}
 
-		if((pid < 16) || (pid == 8191))		//invalid pid
+
+
+		if(((pid > 1) && (pid < 16)) || (pid == 8191))		//invalid pid
 			continue;
+
 		cc = (packet[3] & 0xf);
 		cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));
 		if(! cc_ok)
@@ -702,54 +1340,167 @@
 		}
 		tss->last_cc = cc;
 
-		/* skip adaptation field */
-		afc = (packet[3] >> 4) & 3;
-		if (afc == 0) /* reserved value */
-			continue;
-		if (afc == 2) /* adaptation field only */
-			continue;
-		if (afc == 3)
+
+		if(! priv->is_synced)
 		{
-			int c;
-			stream_read(stream, &packet[_read], 1);
-			c = packet[_read];
-			_read++;
+			priv->last_afc = 0;
+			/* skip adaptation field */
+			afc = (packet[3] >> 4) & 3;
+			if (afc == 0) /* reserved value */
+				continue;
+			if (afc == 2) /* adaptation field only */
+				continue;
+			if (afc == 3)
+			{
+				int c;
+				stream_read(stream, &packet[_read], 1);
+				c = packet[_read];
+				_read++;
 
-			c = min(c, priv->ts.packet_size - _read);
-			stream_read(stream, &packet[_read], c);
-			_read += c;
+				c = min(c, priv->ts.packet_size - _read);
+				stream_read(stream, &packet[_read], c);
+				_read += c;
+
+				priv->last_afc = c + 1;
+				mp_msg(MSGT_DEMUX, MSGL_DBG2, "AFC: %d\n", priv->last_afc);
 
-			if(_read == priv->ts.packet_size)
-			continue;
+				if(_read == priv->ts.packet_size)
+				continue;
+			}
+		}
+		else
+		{
+			_read += priv->last_afc;
+			priv->last_afc = 0;
 		}
 
 		// PES CONTENT STARTS HERE
 
 		buf_size = priv->ts.packet_size - _read;
 
-		if(! probe)
+		//LET'S PARSE TABLES
+
+		if(pid  == 0)
 		{
-			if((tss->type == VIDEO_MPEG2) && (demuxer->video->id == tss->pid))
-				ds = demuxer->video;
-			else if(((tss->type == AUDIO_MP2) || (tss->type == AUDIO_A52) || (tss->type == AUDIO_LPCM_BE))
-					&& (demuxer->audio->id == tss->pid))
-				ds = demuxer->audio;
-			else
+			stream_read(stream,&packet[_read], buf_size);
+			parse_pat(priv, is_start, &packet[_read], buf_size);
+			priv->is_synced = 0;
+			continue;
+		}
+		else
+		{
+			progid = prog_id_in_pat(priv, pid);
+			if(((progid != -1) || (pid == 16)))
 			{
-				stream_read(stream, tmp, buf_size);
-				_read += buf_size;
+				stream_read(stream,&packet[_read], buf_size);
+				parse_pmt(priv, progid, pid, is_start, &packet[_read], buf_size);
+				priv->is_synced = 0;
 				continue;
 			}
 		}
 
 
+
+		if(! probe)
+		{
+			if(((tss->type == VIDEO_MPEG1) || (tss->type == VIDEO_MPEG2) || (tss->type == VIDEO_MPEG4))
+				&& (demuxer->video->id == tss->pid))
+			{
+				ds = demuxer->video;
+
+				dp = &priv->fifo[1].pack;
+				dp_offset = &priv->fifo[1].offset;
+				buffer_size = &priv->fifo[1].buffer_size;
+				broken = &priv->fifo[1].broken;
+			}
+			else if(((tss->type == AUDIO_MP2) || (tss->type == AUDIO_A52) || (tss->type == AUDIO_LPCM_BE) || (tss->type == AUDIO_AAC))
+					&& (demuxer->audio->id == tss->pid))
+			{
+				ds = demuxer->audio;
+
+				dp = &priv->fifo[0].pack;
+				dp_offset = &priv->fifo[0].offset;
+				buffer_size = &priv->fifo[0].buffer_size;
+				broken = &priv->fifo[0].broken;
+			}
+			else
+			{
+				stream_skip(stream, buf_size);
+				_read += buf_size;
+				continue;
+			}
+
+			//IS IT TIME TO QUEUE DATA to the dp_packet?
+			if(is_start && (*dp != NULL) && (*dp_offset > 0))
+			{
+				priv->last_pid = pid;
+				priv->is_synced = 1;
+				priv->is_start = is_start;
+
+				if(! *broken)
+				{
+					int ret = *dp_offset;
+					resize_demux_packet(*dp, ret);	//shrinked to the right size
+
+					ds_add_packet(ds, *dp);
+					mp_msg(MSGT_DEMUX, MSGL_V, "ADDED %d  bytes to %s fifo, PTS=%f\n", ret, (ds == demuxer->audio ? "audio" : "video"), (*dp)->pts);
+
+
+					*dp = NULL;
+					*dp_offset = 0;
+
+					return -ret;
+				}
+				else
+				{
+					mp_msg(MSGT_DEMUX, MSGL_V, "BROKEN PES, DISCARDING\n");
+					free_demux_packet(*dp);
+
+					*dp = NULL;
+					*dp_offset = 0;
+
+					continue;
+				}
+			}
+
+			priv->last_pid = pid;
+
+			if(*dp == NULL)
+			{
+				*dp = new_demux_packet(*buffer_size);	//es->size
+				*dp_offset = 0;
+				if(! *dp)
+				{
+					fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", *buffer_size);
+					continue;
+				}
+				mp_msg(MSGT_DEMUX, MSGL_DBG2, "CREATED DP(%d)\n", *buffer_size);
+			}
+
+			mp_msg(MSGT_DEMUX, MSGL_DBG2, "NOW PACKET_SIZE = %d, DP_OFFSET = %d\n", *buffer_size, *dp_offset);
+		}
+
+		priv->is_synced = 0;
+
+
 		if(is_start)
 		{
+			mp_msg(MSGT_DEMUX, MSGL_DBG2, "IS_START\n");
+
+			//priv->is_synced = 0;
+
 			p = &packet[_read];
 			stream_read(stream, p, buf_size);
 			_read += buf_size;
 
-			len = pes_parse2(p, buf_size, es);
+			pid_idx = es_pid_in_pmt(priv->pmt, pid);
+			if(pid_idx == -1)
+				pid_type = UNKNOWN;
+			else
+				pid_type = priv->pmt->es[pid_idx].type;
+
+
+			len = pes_parse2(p, buf_size, es, pid_type);
 
 			if(len)
 			{
@@ -772,29 +1523,35 @@
 
 				tss->payload_size = es->payload_size;
 
-				mp_msg(MSGT_DEMUX, MSGL_V, "ts_parse, NOW tss->PSIZE=%u\n", tss->payload_size);
+				mp_msg(MSGT_DEMUX, MSGL_DBG2, "ts_parse, NOW tss->PSIZE=%u\n", tss->payload_size);
 
+				demuxer->filepos = stream_tell(demuxer->stream) - es->size;
 
 				if(probe)
 					return es->size;
 				else
 				{
-					dp = new_demux_packet(es->size);
-					if(! dp || ! dp->buffer)
+					*broken = 0;
+					if(*dp_offset + es->size > *buffer_size)
 					{
-						fprintf(stderr, "fill_buffer, NEW_ADD_PACKET(%d)FAILED\n", es->size);
-						continue;
+						*buffer_size = *dp_offset + es->size + TS_FEC_PACKET_SIZE;
+						resize_demux_packet(*dp, *buffer_size);
+						//we'll skip at least one RESIZE() in the next iteration of ts_parse()
+						mp_msg(MSGT_DEMUX, MSGL_DBG2, "RESIZE DP TO %d\n", *buffer_size);
 					}
+					memcpy(&((*dp)->buffer[*dp_offset]), es->start, es->size);
+					*dp_offset += es->size;
+					(*dp)->flags = 0;
+					(*dp)->pts = es->pts;
+					(*dp)->pos = stream_tell(demuxer->stream);
+					*broken = 0;
+					mp_msg(MSGT_DEMUX, MSGL_DBG2, "INIT PACKET, TYPE=%x, PTS: %f\n", es->type, es->pts);
 
-					memcpy(dp->buffer, es->start, es->size);
-					dp->flags = 0;
-					dp->pts = es->pts;
-					dp->pos = stream_tell(demuxer->stream);
-					ds_add_packet(ds, dp);
-
-					return -es->size;
+					continue;
 				}
 			}
+			else
+				return 0;
 		}
 		else
 		{
@@ -802,10 +1559,11 @@
 
 			if(tss->type == UNKNOWN)
 			{
-				stream_read(stream, tmp, buf_size);
+				stream_skip(stream, buf_size);
 				continue;
 			}
 
+
 			es->pid = tss->pid;
 			es->type = tss->type;
 			es->pts = tss->pts = tss->last_pts;
@@ -820,26 +1578,34 @@
 			}
 			else
 			{
-				if(es->type == VIDEO_MPEG2)
+				if((es->type == VIDEO_MPEG1) || (es->type == VIDEO_MPEG2) || (es->type == VIDEO_MPEG4))
 					sz = es->size = buf_size;
 				else
 				{
-					stream_read(stream, tmp, buf_size);
+					stream_skip(stream, buf_size);
 					continue;
 				}
 			}
 
 
-
 			if(! probe)
 			{
-				ds_read_packet(ds, stream, sz, tss->last_pts, stream_tell(stream), 0);
-				if(buf_size - sz)
-					stream_read(stream, tmp, buf_size - sz);
+				if(*dp_offset + sz > *buffer_size)
+				{
+					*buffer_size = *dp_offset + sz + TS_FEC_PACKET_SIZE;
+					resize_demux_packet(*dp, *buffer_size);
+					//we'll skip at least one RESIZE() in the next iteration of ts_parse()
+					mp_msg(MSGT_DEMUX, MSGL_DBG2, "RESIZE DP TO %d\n", *buffer_size);
+				}
 
-				mp_msg(MSGT_DEMUX, MSGL_V, "DOPO DS_READ_PACKET pid %d, size %d DS=%p\n", tss->pid, sz, ds);
-				return -sz;
+
+				stream_read(stream, &((*dp)->buffer[*dp_offset]), sz);
+				*dp_offset += sz;
 
+				if(buf_size - sz)
+					stream_skip(stream, buf_size - sz);
+
+				continue;
 			}
 			else
 			{
@@ -860,6 +1626,120 @@
 }
 
 
+extern void resync_audio_stream(sh_audio_t *sh_audio);
+extern void skip_audio_frame(sh_audio_t *sh_audio);
+
+static void reset_fifos(ts_priv_t* priv, int a, int v)
+{
+	if(a)
+	{
+		priv->fifo[0].pack = NULL;
+		priv->fifo[0].offset = 0;
+		priv->fifo[0].buffer_size = 0;
+		priv->fifo[0].broken = 1;
+		priv->is_synced = 0;
+	}
+
+	if(v)
+	{
+		priv->fifo[1].pack = NULL;
+		priv->fifo[1].offset = 0;
+		priv->fifo[1].buffer_size = 0;
+		priv->fifo[1].broken = 1;
+		priv->is_synced = 0;
+	}
+}
+
+void demux_seek_ts(demuxer_t *demuxer,float rel_seek_secs,int flags)
+{
+	demux_stream_t *d_audio=demuxer->audio;
+	demux_stream_t *d_video=demuxer->video;
+	sh_audio_t *sh_audio=d_audio->sh;
+	sh_video_t *sh_video=d_video->sh;
+	ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
+	int i, video_stats;
+
+	//================= seek in MPEG ==========================
+	off_t newpos = (flags&1)?demuxer->movi_start:demuxer->filepos;
+
+	ts_dump_streams(demuxer->priv);
+	reset_fifos(priv, sh_audio != NULL, sh_video != NULL);
+
+
+	video_stats = (sh_video != NULL);
+	if(video_stats)
+		video_stats = sh_video->i_bps;
+
+	if(flags & 2) // float seek 0..1
+		newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs;
+	else
+	{
+		// time seek (secs)
+
+		if(! video_stats) // unspecified or VBR
+			newpos += 2324*75*rel_seek_secs; // 174.3 kbyte/sec
+		else
+			newpos += video_stats*rel_seek_secs;
+	}
+
+
+	if(newpos<demuxer->movi_start)
+  		newpos = demuxer->movi_start = 0;	//begininng of stream
+
+#ifdef _LARGEFILE_SOURCE
+	newpos &= ~((long long) (STREAM_BUFFER_SIZE - 1));  /* sector boundary */
+#else
+	newpos &= ~(STREAM_BUFFER_SIZE - 1);  /* sector boundary */
+#endif
+
+	reset_fifos(priv, sh_audio != NULL, sh_video != NULL);
+
+	if(sh_audio != NULL)
+		ds_free_packs(d_audio);
+	if(sh_video != NULL)
+		ds_free_packs(d_video);
+
+	stream_seek(demuxer->stream, newpos);
+
+
+	if(sh_video != NULL)
+		ds_fill_buffer(d_video);
+
+	if(sh_audio != NULL)
+	{
+		ds_fill_buffer(d_audio);
+		resync_audio_stream(sh_audio);
+	}
+
+	while(sh_video != NULL)
+	{
+		if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts)
+		{
+			float a_pts=d_audio->pts;
+			a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
+			if(d_video->pts>a_pts)
+			{
+				skip_audio_frame(sh_audio);  // sync audio
+				continue;
+			}
+		}
+
+
+		i = sync_video_packet(d_video);
+		if(sh_video->format == VIDEO_MPEG1 || sh_video->format == VIDEO_MPEG2)
+		{
+			if(i==0x1B3 || i==0x1B8) break; // found it!
+		}
+		else //MPEG4
+		{
+			if(i==0x1B6) break; // found it!
+		}
+
+		if(!i || !skip_video_packet(d_video)) break; // EOF?
+	}
+}
+
+
 int demux_ts_fill_buffer(demuxer_t * demuxer)
 {
 	ES_stream_t es;
@@ -870,62 +1750,3 @@
 
 
 
-
-int demux_seek_ts(demuxer_t * demuxer, float rel_seek_secs, int flags)
-{
-	int total_bitrate=0;
-	off_t dest_offset;
-	ts_priv_t * priv = demuxer->priv;
-	int a_bps, v_bps;
-	demux_stream_t *d_audio=demuxer->audio;
-	demux_stream_t *d_video=demuxer->video;
-	sh_audio_t *sh_audio=d_audio->sh;
-	sh_video_t *sh_video=d_video->sh;
-
-
-	/*
-	 * Compute absolute offset inside the stream. Approximate total bitrate with sum of bitrates
-	 * reported by the audio and video codecs. The seek is not accurate because, just like
-	 * with MPEG streams, the bitrate is not constant. Moreover, we do not take into account
-	 * the overhead caused by PVA and PES headers.
-	 * If the calculated absolute offset is negative, seek to the beginning of the file.
-
-	 */
-
-
-	if(demuxer->audio->id != -2)
-	{
-		a_bps = ((sh_audio_t *)demuxer->audio->sh)->i_bps;
-		total_bitrate += a_bps;
-	}
-
-	if(demuxer->video->id != -2)
-	{
-		v_bps = ((sh_video_t *)demuxer->video->sh)->i_bps;
-		total_bitrate += v_bps;
-	}
-
-	if(! total_bitrate)
-	{
-		mp_msg(MSGT_DEMUX, MSGL_V, "SEEK_TS, couldn't determine bitrate, no seek\n");
-		return 0;
-	}
-
-	dest_offset = stream_tell(demuxer->stream) + rel_seek_secs*total_bitrate;
-	if(dest_offset < 0) dest_offset = 0;
-
-	mp_msg(MSGT_DEMUX, MSGL_V, "SEEK TO: %f, BITRATE: %lu, FINAL_POS: %u \n", rel_seek_secs, total_bitrate, dest_offset);
-
-	stream_seek(demuxer->stream, dest_offset);
-
-	ds_fill_buffer(d_video);
-	if(sh_audio)
-	{
-		ds_fill_buffer(d_audio);
-		resync_audio_stream(sh_audio);
-	}
-
-	return 1;
-}
-
-