[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