[MPlayer-dev-eng] Ac3 streams detected as LPCM or SPU in TS

MichaelM lordvader at swiftdsl.com.au
Wed Jun 16 18:44:13 CEST 2004


Coolness!
I've tested the patch with as many ac3 streams I have available. With a 
tsprobe parameter of 50000000, the ac3 streams are detected, and played 
back.

I have encountered numerous sync issues, but at the moment I'll assume 
its my computers fault. Most of the sync issues are gone when I capture 
the stream to disk and then playback.
There are a few a52 crc errors, like so:
   a52: CRC check failed!   -0.054 ct: -0.348  727/727  27% 33%  3.3% 0 
0   0%
   a52: error at resampling

Also, occasionally this error occurs, during which video slows down, and 
then audio playback ceases, with video resuming:
   Too many video packets in the buffer: (11 in 8432596 bytes).
   Maybe you are playing a non-interleaved stream/file or the codec failed?
   For AVI files, try to force non-interleaved mode with the -ni option.

Again, most of these errors may be my systems fault (Athlon XP 2.3GHz, 
with a radeon9500, using the xfree86 drivers).

BTW, I haven't  really played around with the tsprobe parameter, so its 
likely that a smaller value will work. 50000000 works, but it is 
somewhat slow.



nsabbi at fastwebnet.it wrote:
>>-- Original Message --
>>Date: Wed, 16 Jun 2004 05:00:28 +1000
>>From: MichaelM <lordvader at swiftdsl.com.au>
>>To: mplayer-dev-eng at mplayerhq.hu
>>Subject: Re: [MPlayer-dev-eng] Ac3 streams detected as LPCM or SPU in TS
>>Reply-To: mplayer-dev-eng at mplayerhq.hu
>>
>>
>>That's cool. I'm just trying to understand how this all fits together :)
>>
>>
> 
> 
> For the time being this patch should work
> (provided you specify a large enough -tsprobe parameter).
> I still have to make sure that PES_PRIVATE1 has a lower priority
> than all other audio codecs during the probe phase.
> Please, test the patch on a large number of samples (especially
> from the same transmitter of that "channel9hdtv.ts" sample that you
> uploaded) and report ASAP.
> 
>              Nico
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> Index: demux_ts.c
> ===================================================================
> RCS file: /cvsroot/mplayer/main/libmpdemux/demux_ts.c,v
> retrieving revision 1.14
> diff -c -u -r1.14 demux_ts.c
> --- demux_ts.c	31 May 2004 16:12:13 -0000	1.14
> +++ demux_ts.c	15 Jun 2004 21:35:58 -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,15 +373,46 @@
>  	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 - 8)	
> +	{
> +		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_INFO, "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;
> -	int is_audio, is_video, is_sub, has_tables;
> +	int is_audio, is_video, is_sub, has_tables, audio_size = 0, left = MAX_A52_FRAME_SIZE * 6;
>  	int32_t p, chosen_pid = 0;
>  	off_t pos=0, ret = 0, init_pos;
>  	ES_stream_t es;
>  	unsigned char tmp[TS_FEC_PACKET_SIZE];
>  	ts_priv_t *priv = (ts_priv_t*) demuxer->priv;
> +	char audio_buf[MAX_A52_FRAME_SIZE * 6];
>  
>  	priv->last_pid = 8192;		//invalid pid
>  
> @@ -388,6 +421,7 @@
>  	req_spid = param->spid;
>  
>  	has_tables = 0;
> +	bzero(audio_buf, MAX_A52_FRAME_SIZE * 6);
>  	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,11 +429,11 @@
>  		pos = stream_tell(demuxer->stream);
>  		if(ts_parse(demuxer, &es, tmp, 1))
>  		{
> -			is_audio = ((es.type == AUDIO_MP2) || (es.type == AUDIO_A52) || (es.type == AUDIO_LPCM_BE) || (es.type == AUDIO_AAC));
> +			is_audio = ((es.type == AUDIO_MP2) || (es.type == AUDIO_A52) || (es.type == AUDIO_LPCM_BE) || (es.type == AUDIO_AAC) 
> +				|| (es.type == PES_PRIVATE1));
>  			is_video = ((es.type == VIDEO_MPEG1) || (es.type == VIDEO_MPEG2) || (es.type == VIDEO_MPEG4));
>  			is_sub   = ((es.type == SPU_DVD) || (es.type == SPU_DVB));
>  
> -
>  			if((! is_audio) && (! is_video) && (! is_sub))
>  				continue;
>  
> @@ -481,8 +515,7 @@
>  
>  
>  			mp_msg(MSGT_DEMUXER, MSGL_DBG2, "TYPE: %x, PID: %d, PROG FOUND: %d\n", es.type, es.pid, param->prog);
> -
> -
> +			
>  			if(is_video)
>  			{
>  				if((req_vpid == -1) || (req_vpid == es.pid))
> @@ -494,13 +527,32 @@
>  			}
>  
>  
> -			if(((req_vpid == -2) || (num_packets >= NUM_CONSECUTIVE_AUDIO_PACKETS)) && audio_found)
> +			if(((req_vpid == -2) || (num_packets >= NUM_CONSECUTIVE_AUDIO_PACKETS)) && (audio_found && (audio_size == left)))
>  			{
>  				//novideo or we have at least 348 audio packets (64 KB) without video (TS with audio only)
>  				param->vtype = 0;
>  				break;
>  			}
>  
> +			if(is_audio)
> +			{
> +				if((req_apid == -1) || (req_apid == es.pid))
> +				{
> +					param->atype = es.type;
> +					param->apid = es.pid;
> +					audio_found = 1;
> +				}
> +
> +				//buffer data that we need later to check if (there are no tables && audio may be A52)
> +				mp_msg(MSGT_DEMUXER, MSGL_V, "AUDIO_SIZE: %d, LEFT: %d, ES_SIZE: %d\n", audio_size, left, es.size);
> +				if(audio_size < left)
> +				{
> +					es.size = min(es.size, left - audio_size);
> +					memcpy(&audio_buf[audio_size], es.start, es.size);
> +					audio_size += es.size;
> +				}
> +			}
> +			
>  			if(is_sub)
>  			{
>  				if((req_spid == -1) || (req_spid == es.pid))
> @@ -511,15 +563,7 @@
>  				}
>  			}
>  
> -			if(is_audio)
> -			{
> -				if((req_apid == -1) || (req_apid == es.pid))
> -				{
> -					param->atype = es.type;
> -					param->apid = es.pid;
> -					audio_found = 1;
> -				}
> -			}
> +			
>  
>  			if(audio_found && (param->apid == es.pid) && (! video_found))
>  				num_packets++;
> @@ -530,11 +574,20 @@
>  				break;
>  			}
>  
> -			if((has_tables==0) && (video_found && audio_found) && (pos >= 1000000))
> +			if((has_tables==0) && (video_found && audio_found && (audio_size == left)) && (pos >= 1000000))
>  				break;
>  		}
>  	}
>  
> +	//Non PES-aligned A52 audio may escape detection if PMT is not present;
> +	//in this case we try to find at least 4 A52 syncwords
> +	if(audio_found && (param->atype == PES_PRIVATE1) && (has_tables==0))
> +	{
> +		mp_msg(MSGT_DEMUXER, MSGL_INFO, "AUDIO_BUFFER_SIZE: %d\n", audio_size);
> +		if(a52_check(audio_buf, audio_size) >= 4)
> +			param->atype = AUDIO_A52;
> +	}
> +	
>  	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
> @@ -545,8 +598,9 @@
>  		mp_msg(MSGT_DEMUXER, MSGL_INFO, "NO VIDEO! ");
>  	}
>  
> +	
>  	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 +616,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,13 +793,9 @@
>  	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 +831,7 @@
>  	}
>  
>  	es->payload_size = (p[4] << 8 | p[5]);
> +	pes_is_aligned = (p[6] & 4);
>  
>  	stream_id  = p[3];
>  
> @@ -798,33 +849,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 +873,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 +899,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 +908,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 +928,7 @@
>  
>  			return 1;
>  		}
> -		else if ((p[0]&0xf0) == 0xa0)
> +		else if (pes_is_aligned && ((p[0]&0xf0) == 0xa0))
>  		{
>  			int pcm_offset;
>  
> @@ -929,6 +948,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))
>  	{
> @@ -1630,7 +1659,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 +1783,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);
>  
> @@ -1852,10 +1882,7 @@
>  				*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);
>  			}
>  
> @@ -1872,15 +1899,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 +1949,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 +1961,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
>  		{
> @@ -1989,6 +2032,7 @@
>  
>  				if(is_audio)
>  				{
> +					(*dp)->pts = tss->last_pts;
>  					retv = fill_packet(demuxer, ds, dp, dp_offset);
>  					return 1;
>  				}
> @@ -1998,7 +2042,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;
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> MPlayer-dev-eng mailing list
> MPlayer-dev-eng at mplayerhq.hu
> http://mplayerhq.hu/mailman/listinfo/mplayer-dev-eng




More information about the MPlayer-dev-eng mailing list