[MPlayer-dev-eng] Re: AC-3 in a TS stream

Trent Piepho xyzzy at speakeasy.org
Tue Feb 28 11:07:08 CET 2006


> From: Nico Sabbi <nicola_sabbi at fastwebnet.it>
> Subject: Re: [MPlayer-dev-eng] AC-3 in a TS stream
> 
> >>not exact: it will be marked as PES_PRIVATE1 and ac3 probing will happen 
> >>in a52_check()
> >>    
> >
> >It looks like this doesn't work.  I wrote a perl script to parse the output
> >of mplayer's debug messages and ran:
> >
> 
> in this case my code is buggy. I'll fix it this week-end, if possible.
> Can you post a link to this sample, please? I need a lot of them to test 
> the code

http://www.speakeasy.org/~xyzzy/download/ktwb-[1259].ts.bz2

1 & 2 don't work (all detected private1), 5 & 9 do (ac3 DVD VOB (incorrectly)
detected).

I think there might be a potential bug in the pes_parse2() code.  You know
this I'm sure, but I'll say it anyway.  All kinds of PES packets have a 6 byte
header.  Most PES packets, but not all, have a 3+ byte header after that.  If
the stream_id is for example private2 or padding, the second 3+ byte header
isn't present.  The code in pes_parse2() doesn't check stream_id, and will
always try to parse the optional 3+ byte header, even when it doesn't exist.

I think all that can go wrong is the ts_demux might spit out bogus error
messages, and it will mangle that PES stream.  mplayer can't do anything with
private2 or the other types, so it hardly matters that the data is mangled.

> >I think there is a bug in the way a52_check is called.  If you look at the
> >input bytes for a52_check, it goes up by 168 for each PES packet.  That is
> >only one TS packet's worth of data.  It looks like the rest of the audio TS
> >packets that make up the PES packet are not getting passed to a52_check, and
> >so the check fails.
> >
> 
> I guess I know why: other initial bytes than 0x8n in the next payload 
> packet will make
> demux_ts forget that previously it found a PES_PRIVATE1 stream

Hmm, why do you think this?  I thought the only check for 0x8n was inside
pes_parse2().  pes_parse2() is only called for the first TS packet in a PES
packet, when is_start is 1.  When is_start is zero pes_parse2() is never
called and there isn't any kind of check for 0x8n in the payload.

It seems pretty clear to me from the log I posted that only the first TS
packet of a PES packet (when is_start==1) is sent to a52_check().  The rest
of the TS packets in the PES packet (when is_start==0) are just discarded.

I think the problem might be in ts_parse().  When in probe mode
tss->payload_size is never set to es->payload_size.  This means ts_parse()
just skips is_start==0 TS packets and doesn't add them to the PES packet and
so a52_check will never see them.  At least this appears to fix the
problem for me.

> >I am confused about this.  You say there is no AC3 syncword after the DVD VOB
> >sub-header, but the patch you later provided checks for an AC3 syncword after
> >the DVD VOB header for the DVD VOB style AC3 format.
> 
> yes, but in any position in the payload of the current packet

It looks like you only detect the DVD VOB format, and skip the 4-byte
sub-stream header, when the AC3 syncword appears right after a possible 4-byte
sub-stream header.  If the PES packet has 0x8 as the first four bits and has
0x0b77 somewhere in the first ~168 bytes but NOT exactly 4-bytes in, it's
detected as AC3 with no VOB sub-header.


> >Anyway, I looked at how mplex and dvdauthor deal with DVD VOB AC3 sub-headers,
> >since there is no spec I could find.  This is what I found:
> >
> >dvdauthor will only look for a sub-header if the PTS_DTS flag is set in the
> >PES header.
> >
> the sub header is always needed, even with no pts/dts

So what you are saying is that you have seen TS streams where the AC3 PES
packets had a DVD VOB sub-header but the pts/dts flag in the PES header
_wasn't_ set?  dvdauthor would not accept this as valid, which doesn't prove
such streams do not exist of course.


> >dvdauthor and mplex expect the AC3 substream ID to be, in binary, 10000xxx,
> >for AC-3 substream xxx.  The code for a DTS substream is 10001xxx.  The TS
> >auto-detect code checks for 1000xxxx, one bit less specific than it could be.
> >  
> >
> of course: it searches AC3.
> 0x80 -> 0x87 : AC3
> 0x88 -> 0x8f : DTS (that I don't want to deal with)

I'm not sure I understand you here.  The code I see in demux_ts.c is this:

                else if ((p[0] & 0xF0) == 0x80)

This is clearly detecting both 0x80 -> 0x87 and 0x88 ->0x8f as AC3.  You are
saying you want to detect DTS as AC3, rather than ignore it or deal with as
DTS?  Or do you mean there is a small bug here, and it should be p[0] & 0xf8
that is checked?  The latter it what I was trying to suggest in my previous
email.

> >The second byte after the sub-stream ID might be some kind of continuity
> >counter.  I'm unsure about this one.  dvdauthor ignores it, mplex sticks
> >something (???) there.  I found an dvd-audio open source project's docs that
> >say it is a continuity counter.
> >
> no, it's the count of AC3 frames present in the current pes packet

Ok, that makes sense.  Couldn't this be checked?  The code knows the size of
the PES packet and AC3 frames have a limited range of valid sizes (128 to 3840
bytes).  For example, a PES with 5KB of payload can only have 1 - 40 AC3
syncwords.  So:

if(p[1]*128-127 >= es->payload_size) { not DVD VOB format }

this would cause fewer false positives of DVD VOB format, but not mess up
detection of real DVD VOB format packets, right?

> >The next two bytes of the sub-stream header are an offset to the start of an
> >AC3 frame.  If the offset is 1 (I think, maybe 2?), then the AC3 frame
> >syncword must start immediately after the sub-stream header.  This is what
> >I suggested before, and what your patch checks for.
> 
> yes

If the offset is 0, does that mean no ac3 frames start in the packet?  Or does
it mean the start location just isn't specified and an AC3 frame may or may
not start in the packet?  Could the offset extend beyond the *PES* packet and
into the next PES packet? 

Could the DVD VOB check include this too?  Something like:

do { /* Not a real loop, just so we can use 'break' like a goto */
    int offset = p[2]<<8 | p[3];

    /* Can specified num of syncwords fit in this PES packet? */
    if(p[1]*128-127 >= es->payload_size)
	break;

    if(p[1] && offset)
    {
    	offset += 3;	/* add 3 to skip over sub-header */

	if(offset > 3840 + 3)
	{
	    /* offset > largest AC3 frame, this is invalid sub-header */  
	    break; /* not dvd vob */
	}
	if(offset+2 <= packet_len)
	{
	    /* AC3 syncword should be inside this TS packet, check it */
	    if(p[offset] != 0x0b || p[offset+1] != 0x77)
		break; /* not dvd vob */
	}
	/* else
	    AC3 syncword check needs more TS packets, can't do it here */
    }
    /* Ok, DVD VOB format maybe detected. Strip sub-header. */
    mp_msg(MSGT_DEMUX, MSGL_DBG2, "A52 WITH DVD VOB HEADER\n");
    es->start   = p + 4;
    es->size    = packet_len - 4;
    es->type    = AUDIO_A52;
    es->payload_size -= packet_len;
    return 1;
} while(0);


> >I'm not sure I understand what you are saying here.  I though tsprobe
> >controlled the amout of data scanned, my mplayer uses 2000000 as the default
> >tsprobe size.  There is something else that is 32KB?
> >  
> >
> 
> 32KB is the default value for -tsprobe. Specifying -tsprobe 2000000 will 
> override the
> default value

Maybe this has changed in the most recent CVS?  In MPlayer-1.0pre7try2:

#define TS_MAX_PROBE_SIZE 2000000 /* dont forget to change this in cfg-common.h too */
off_t ts_probe = TS_MAX_PROBE_SIZE;

I checked that running mplayer without -tsprobe results in the same number of
TS packets getting scanned as with -tsprobe 2000000, while -tsprobe 32768
scans far fewer packets.  32KB is of course far too small for 40 Mbit QAM-256
streams.  Maybe the ts probe max should be increased?  If the PAT and PMT are
sent at the minimum rate, 32KB isn't likely to get them.  It would be even
worse in PAL countries, where QAM-256 can fit something like 52 Mbit/sec in an
8 MHz channel.




More information about the MPlayer-dev-eng mailing list