# HG changeset patch # User nicodvb # Date 1087588925 0 # Node ID a731d98a338253e2507f0187a025936a4dc8f196 # Parent e7c4f5d539e94d4d77820b80f7b3521186adb3e8 added support for ac3 in non-pes aligned private1 streams; removed useless and commented code diff -r e7c4f5d539e9 -r a731d98a3382 libmpdemux/demux_ts.c --- 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;