changeset 12612:a731d98a3382

added support for ac3 in non-pes aligned private1 streams; removed useless and commented code
author nicodvb
date Fri, 18 Jun 2004 20:02:05 +0000
parents e7c4f5d539e9
children c315d377634f
files libmpdemux/demux_ts.c
diffstat 1 files changed, 131 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/demux_ts.c	Fri Jun 18 17:08:22 2004 +0000
+++ b/libmpdemux/demux_ts.c	Fri Jun 18 20:02:05 2004 +0000
@@ -47,6 +47,7 @@
 #define TS_MAX_PROBE_SIZE 2000000 /* dont forget to change this in cfg-common.h too */
 #define NUM_CONSECUTIVE_TS_PACKETS 32
 #define NUM_CONSECUTIVE_AUDIO_PACKETS 348
+#define MAX_A52_FRAME_SIZE 3840
 
 
 int ts_prog;
@@ -65,7 +66,8 @@
 	AUDIO_LPCM_BE  	= 0x10001,
 	AUDIO_AAC	= mmioFOURCC('M', 'P', '4', 'A'),
 	SPU_DVD		= 0x3000000,
-	SPU_DVB		= 0x3000001
+	SPU_DVB		= 0x3000001,
+	PES_PRIVATE1	= 0xBD00000
 } es_stream_type_t;
 
 
@@ -371,6 +373,36 @@
 	off_t probe;
 } tsdemux_init_t;
 
+
+//second stage: returns the count of A52 syncwords found
+static int a52_check(char *buf, int len)
+{
+	int cnt, frame_length, flags, sample_rate, bit_rate, ok;
+	
+	cnt = ok = 0;
+	if(len < 8)
+		return 0;
+		
+	while(cnt < len - 7)	
+	{
+		if(buf[cnt] == 0x0B && buf[cnt+1] == 0x77)
+		{
+			frame_length = a52_syncinfo(&buf[cnt], &flags, &sample_rate, &bit_rate);
+			if(frame_length>=7 && frame_length<=3840)
+			{
+				cnt += frame_length;
+				ok++;
+			}
+		}
+		else
+			cnt++;
+	}
+
+	mp_msg(MSGT_DEMUXER, MSGL_V, "A52_CHECK(%d input bytes), found %d frame syncwords of %d bytes length\n", len, ok, frame_length);	
+	return ok;
+}
+
+
 static off_t ts_detect_streams(demuxer_t *demuxer, tsdemux_init_t *param)
 {
 	int video_found = 0, audio_found = 0, sub_found = 0, i, num_packets = 0, req_apid, req_vpid, req_spid;
@@ -380,6 +412,10 @@
 	ES_stream_t es;
 	unsigned char tmp[TS_FEC_PACKET_SIZE];
 	ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
+	struct {
+		char *buf;
+		int pos;
+	} pes_priv1[8192], *pptr;
 
 	priv->last_pid = 8192;		//invalid pid
 
@@ -388,6 +424,7 @@
 	req_spid = param->spid;
 
 	has_tables = 0;
+	bzero(pes_priv1, sizeof(pes_priv1));
 	init_pos = stream_tell(demuxer->stream);
 	mp_msg(MSGT_DEMUXER, MSGL_INFO, "PROBING UP TO %llu, PROG: %d\n", (uint64_t) param->probe, param->prog);
 	while((pos <= init_pos + param->probe) && (! demuxer->stream->eof))
@@ -395,6 +432,24 @@
 		pos = stream_tell(demuxer->stream);
 		if(ts_parse(demuxer, &es, tmp, 1))
 		{
+			//Non PES-aligned A52 audio may escape detection if PMT is not present;
+			//in this case we try to find at least 3 A52 syncwords
+			if((es.type == PES_PRIVATE1) && (! audio_found))
+			{
+				pptr = &pes_priv1[es.pid];
+				pptr->buf = (char*) realloc(pptr->buf, pptr->pos + es.size);
+				if(pptr->buf != NULL)
+				{
+					memcpy(&(pptr->buf[ pptr->pos ]), es.start, es.size);
+					pptr->pos += es.size;
+					if(a52_check(pptr->buf, pptr->pos) > 2)
+					{
+						param->atype = AUDIO_A52;
+						es.type = AUDIO_A52;
+					}
+				}
+			}
+			
 			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));
 			is_sub   = ((es.type == SPU_DVD) || (es.type == SPU_DVB));
@@ -535,6 +590,16 @@
 		}
 	}
 
+	for(i=0; i<8192; i++)
+	{
+		if(pes_priv1[i].buf != NULL)
+		{
+			free(pes_priv1[i].buf);
+			pes_priv1[i].buf = NULL;
+			pes_priv1[i].pos = 0;
+		}
+	}
+						
 	if(video_found)
 		mp_msg(MSGT_DEMUXER, MSGL_INFO, "VIDEO MPEG%d(pid=%d)...", (param->vtype == VIDEO_MPEG1 ? 1 : (param->vtype == VIDEO_MPEG2 ? 2 : 4)), param->vpid);
 	else
@@ -546,7 +611,7 @@
 	}
 
 	if(param->atype == AUDIO_MP2)
-		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MP2(pid=%d)", param->apid);
+		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO MPA(pid=%d)", param->apid);
 	else if(param->atype == AUDIO_A52)
 		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO A52(pid=%d)", param->apid);
 	else if(param->atype == AUDIO_LPCM_BE)
@@ -562,7 +627,7 @@
 	}
 
 	if(param->stype == SPU_DVD || param->stype == SPU_DVB)
-		mp_msg(MSGT_DEMUXER, MSGL_INFO, " SUB DVx(pid=%d) ", param->spid);
+		mp_msg(MSGT_DEMUXER, MSGL_INFO, " SUB %s(pid=%d) ", (param->stype==SPU_DVD ? "DVD" : "DVB"), param->spid);
 	else
 	{
 		param->stype = UNKNOWN;
@@ -739,12 +804,7 @@
 	uint32_t       header_len;
 	int64_t        pts;
 	uint32_t       stream_id;
-	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;
+	uint32_t       pkt_len, pes_is_aligned;
 
 	//Here we are always at the start of a PES packet
 	mp_msg(MSGT_DEMUX, MSGL_DBG2, "pes_parse2(%p, %d): \n", buf, (uint32_t) packet_len);
@@ -781,6 +841,7 @@
 	}
 
 	es->payload_size = (p[4] << 8 | p[5]);
+	pes_is_aligned = (p[6] & 4);
 
 	stream_id  = p[3];
 
@@ -798,33 +859,6 @@
 	else
 		es->pts = 0.0f;
 
-	/*
-	CODE TO CALCULATE ES_RATE AND ESCR, ACTUALLY UNUSED BUT POSSIBLY NEEDED IN THE FUTURE
-
-	pts_flag = ((p[7] & 0xc0) >> 6) & 3;
-	escr_flag = p[7] & 0x20;
-	es_rate_flag = p[7] & 0x10;
-	mp_msg(MSGT_DEMUX, MSGL_V, "pes_parse: ES_RATE_FLAG=%d, ESCR_FLAG=%d, PTS_FLAG=%d, byte=%02X\n", es_rate_flag, escr_flag, pts_flag, p[7]);
-
-
-	if(es_rate_flag)
-	{
-		char *base;
-		int bytes = 0;
-
-		if(pts_flag == 2)
-			bytes += 5;
-		else if(pts_flag == 3)
-			bytes += 10;
-
-		if(escr_flag)
-			bytes += 6;
-
-		base = p[8+bytes];
-		es_rate = ((base[0] & 0x7f) << 8) | (base[1] << 8) | (base[0] & 0xfe);
-		mp_msg(MSGT_DEMUX, MSGL_V, "demux_ts: ES_RATE=%d)\n", es_rate*50);
-	}
-	*/
 
 	header_len = p[8];
 
@@ -849,14 +883,9 @@
 
 	if (stream_id == 0xbd)
 	{
-		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);
 
-		track = p[0] & 0x0F;
-		mp_msg(MSGT_DEMUX, MSGL_DBG2, "A52 TRACK: %d\n", track);
-
 
 		/*
 		* we check the descriptor tag first because some stations
@@ -880,7 +909,7 @@
 		}
 		/* SPU SUBS */
 		else if(type_from_pmt == SPU_DVB ||
-		(p[0] == 0x20)) // && p[1] == 0x00))
+		((p[0] == 0x20) && pes_is_aligned)) // && p[1] == 0x00))
 		{
 			es->start = p;
 			es->size  = packet_len;
@@ -889,7 +918,7 @@
 
 			return 1;
 		}
-		else if ((p[0] & 0xE0) == 0x20)	//SPU_DVD
+		else if (pes_is_aligned && ((p[0] & 0xE0) == 0x20))	//SPU_DVD
 		{
 			//DVD SUBS
 			es->start   = p+1;
@@ -909,7 +938,7 @@
 
 			return 1;
 		}
-		else if ((p[0]&0xf0) == 0xa0)
+		else if (pes_is_aligned && ((p[0]&0xf0) == 0xa0))
 		{
 			int pcm_offset;
 
@@ -929,6 +958,16 @@
 
 			return 1;
 		}
+		else
+		{
+			mp_msg(MSGT_DEMUX, MSGL_DBG2, "PES_PRIVATE1\n");
+			es->start   = p;
+			es->size    = packet_len;
+			es->type    = PES_PRIVATE1;
+			es->payload_size -= packet_len;
+
+			return 1;
+		}
 	}
 	else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0))
 	{
@@ -1582,7 +1621,7 @@
 			resize_demux_packet(*dp, ret);	//shrinked to the right size
 			ds_add_packet(ds, *dp);
 			mp_msg(MSGT_DEMUX, MSGL_DBG2, "ADDED %d  bytes to %s fifo, PTS=%f\n", ret, (ds == demuxer->audio ? "audio" : (ds == demuxer->video ? "video" : "sub")), (*dp)->pts);
-		}
+	}
 
 	*dp = NULL;
 	*dp_offset = 0;
@@ -1630,7 +1669,7 @@
 
 		if(! ts_sync(stream))
 		{
-			mp_msg(MSGT_DEMUX, MSGL_DBG2, "TS_PARSE: COULDN'T SYNC\n");
+			mp_msg(MSGT_DEMUX, MSGL_INFO, "TS_PARSE: COULDN'T SYNC\n");
 			return 0;
 		}
 
@@ -1754,7 +1793,8 @@
 		priv->last_pid = pid;
 
 		is_video = ((tss->type == VIDEO_MPEG1) || (tss->type == VIDEO_MPEG2) || (tss->type == VIDEO_MPEG4));
-		is_audio = ((tss->type == AUDIO_MP2) || (tss->type == AUDIO_A52) || (tss->type == AUDIO_LPCM_BE) ||  (tss->type == AUDIO_AAC));
+		is_audio = ((tss->type == AUDIO_MP2) || (tss->type == AUDIO_A52) || (tss->type == AUDIO_LPCM_BE) ||  (tss->type == AUDIO_AAC) 
+			|| (tss->type == PES_PRIVATE1));
 		is_sub	= ((tss->type == SPU_DVD) || (tss->type == SPU_DVB));
 		pid_type = pid_type_from_pmt(priv, pid);
 
@@ -1872,15 +1912,41 @@
 			stream_read(stream, p, buf_size);
 
 			len = pes_parse2(p, buf_size, es, pid_type);
-
-			if(len > 0)
+			es->pid = tss->pid;
+					
+			if(probe)
 			{
 				if(es->type == UNKNOWN)
-					continue;
-
-				es->pid = tss->pid;
-				tss->type = es->type;
-
+					return 0;
+				if(len == 0)
+				{
+					if(tss->type != UNKNOWN)
+					{
+						es->size = buf_size;
+						es->start = p;
+						return 1;
+					}
+				}
+				else
+				{
+					tss->type = es->type;
+					return 1;
+				}
+			}
+			else
+			{
+				if(len == 0)
+				{
+					if(tss->type != UNKNOWN)
+					{
+						len = es->size = buf_size;		//push the whole packet to the fifo 
+											//(we already learned what it is during the probe phase)
+						es->start = p;
+					}
+					else
+						continue;
+				}
+					
 				if((es->pts < tss->last_pts) && es->pts)
 					mp_msg(MSGT_DEMUX, MSGL_DBG2, "BACKWARDS PTS! : NEW: %f -> LAST: %f, PID %d\n", es->pts, tss->last_pts, tss->pid);
 
@@ -1896,12 +1962,6 @@
 
 				demuxer->filepos = stream_tell(demuxer->stream) - es->size;
 
-				if(probe)
-					return 1; //es->size;
-				else
-				{
-					if(es->size > 0)
-					{
 						if(*dp_offset + es->size > *buffer_size)
 						{
 							*buffer_size = *dp_offset + es->size + TS_FEC_PACKET_SIZE;
@@ -1914,22 +1974,18 @@
 						(*dp)->flags = 0;
 						(*dp)->pos = stream_tell(demuxer->stream);
 						(*dp)->pts = es->pts;
-					}
 
-					if(retv > 0)
-						return retv;
-					else
-						continue;
-				}
-				
 				if(is_audio)
 				{
 					retv = fill_packet(demuxer, ds, dp, dp_offset);
 					return 1;
 				}
+				
+				if(retv > 0)
+					return retv;
+				else
+					continue;
 			}
-			else
-				return 0;
 		}
 		else
 		{
@@ -1938,7 +1994,10 @@
 			if(tss->type == UNKNOWN)
 			{
 				stream_skip(stream, buf_size);
-				continue;
+				if(probe)
+					return 0;
+				else
+					continue;
 			}
 
 
@@ -1989,6 +2048,7 @@
 
 				if(is_audio)
 				{
+					(*dp)->pts = tss->last_pts;
 					retv = fill_packet(demuxer, ds, dp, dp_offset);
 					return 1;
 				}
@@ -1998,7 +2058,7 @@
 			else
 			{
 				stream_read(stream, es->start, sz);
-				if(buf_size - sz) stream_read(stream, tmp, buf_size-sz);
+				if(buf_size - sz) stream_skip(stream, buf_size-sz);
 
 				if(es->size)
 					return es->size;