X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmpeg.c;h=b0f45e5343d17da802aa7c8d61130c6f7e11d5cc;hb=8507bde0f3b746875d93db80807f007d38562769;hp=aca9db2bb926019c558e3017f94fe7e9cc9307b4;hpb=3dea63bd7e611b625d135fe9bc8b3cef891bc757;p=ffmpeg diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index aca9db2bb92..b0f45e5343d 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -1,6 +1,6 @@ /* * MPEG1/2 demuxer - * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * * This file is part of FFmpeg. * @@ -67,8 +67,8 @@ static int mpegps_probe(AVProbeData *p) if(code == SYSTEM_HEADER_START_CODE) sys++; else if(code == PRIVATE_STREAM_1) priv1++; else if(code == PACK_START_CODE) pspack++; - else if((code & 0xf0) == VIDEO_ID && pes) vid++; - else if((code & 0xe0) == AUDIO_ID && pes) audio++; + else if((code & 0xf0) == VIDEO_ID && pes) vid++; + else if((code & 0xe0) == AUDIO_ID && pes) audio++; else if((code & 0xf0) == VIDEO_ID && !pes) invalid++; else if((code & 0xe0) == AUDIO_ID && !pes) invalid++; @@ -83,7 +83,7 @@ static int mpegps_probe(AVProbeData *p) return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg if(priv1 + vid + audio > invalid && (priv1+vid+audio)*9 <= pspack*10) return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg - if((!!vid ^ !!audio) && (audio+vid > 1) && !sys && !pspack && p->buf_size>2048) /* PES stream */ + if((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys && !pspack && p->buf_size>2048) /* PES stream */ return AVPROBE_SCORE_MAX/2+2; //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1 @@ -211,8 +211,8 @@ static long mpegps_psm_parse(MpegDemuxContext *m, ByteIOContext *pb) /* at least one es available? */ while (es_map_length >= 4){ - unsigned char type = get_byte(pb); - unsigned char es_id = get_byte(pb); + unsigned char type = get_byte(pb); + unsigned char es_id = get_byte(pb); uint16_t es_info_length = get_be16(pb); /* remember mapping from stream id to stream type */ m->psm_es_type[es_id] = type; @@ -334,15 +334,20 @@ static int mpegps_read_pes_header(AVFormatContext *s, header_len -= 5; } } + if (flags & 0x3f && header_len == 0){ + flags &= 0xC0; + av_log(s, AV_LOG_WARNING, "Further flags set but no bytes left\n"); + } if (flags & 0x01) { /* PES extension */ pes_ext = get_byte(s->pb); header_len--; - if (pes_ext & 0x40) { /* pack header - should be zero in PS */ - goto error_redo; - } /* Skip PES private data, program packet sequence counter and P-STD buffer */ skip = (pes_ext >> 4) & 0xb; skip += skip & 0x9; + if (pes_ext & 0x40 || skip > header_len){ + av_log(s, AV_LOG_WARNING, "pes_ext %X is invalid\n", pes_ext); + pes_ext=skip=0; + } url_fskip(s->pb, skip); header_len -= skip; @@ -385,7 +390,8 @@ static int mpegps_read_pes_header(AVFormatContext *s, if(dts != AV_NOPTS_VALUE && ppos){ int i; for(i=0; inb_streams; i++){ - if(startcode == s->streams[i]->id) { + if(startcode == s->streams[i]->id && + !url_is_streamed(s->pb) /* index useless on streams anyway */) { ff_reduce_index(s, i); av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); } @@ -403,14 +409,23 @@ static int mpegps_read_packet(AVFormatContext *s, { MpegDemuxContext *m = s->priv_data; AVStream *st; - int len, startcode, i, type, codec_id = 0, es_type; + int len, startcode, i, es_type; + enum CodecID codec_id = CODEC_ID_NONE; + enum CodecType type; int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work + uint8_t av_uninit(dvdaudio_substream_type); redo: len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); if (len < 0) return len; + if(startcode == 0x1bd) { + dvdaudio_substream_type = get_byte(s->pb); + url_fskip(s->pb, 3); + len -= 4; + } + /* now find stream */ for(i=0;inb_streams;i++) { st = s->streams[i]; @@ -419,7 +434,7 @@ static int mpegps_read_packet(AVFormatContext *s, } es_type = m->psm_es_type[startcode & 0xff]; - if(es_type > 0){ + if(es_type > 0 && es_type != STREAM_TYPE_PRIVATE_DATA){ if(es_type == STREAM_TYPE_VIDEO_MPEG1){ codec_id = CODEC_ID_MPEG2VIDEO; type = CODEC_TYPE_VIDEO; @@ -453,7 +468,7 @@ static int mpegps_read_packet(AVFormatContext *s, if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1)) codec_id = CODEC_ID_CAVS; else - codec_id = CODEC_ID_MPEG2VIDEO; + codec_id = CODEC_ID_PROBE; type = CODEC_TYPE_VIDEO; } else if (startcode >= 0x1c0 && startcode <= 0x1df) { type = CODEC_TYPE_AUDIO; @@ -461,14 +476,15 @@ static int mpegps_read_packet(AVFormatContext *s, } else if (startcode >= 0x80 && startcode <= 0x87) { type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_AC3; - } else if ((startcode >= 0x88 && startcode <= 0x8f) + } else if ( ( startcode >= 0x88 && startcode <= 0x8f) ||( startcode >= 0x98 && startcode <= 0x9f)) { /* 0x90 - 0x97 is reserved for SDDS in DVD specs */ type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_DTS; } else if (startcode >= 0xa0 && startcode <= 0xaf) { type = CODEC_TYPE_AUDIO; - codec_id = CODEC_ID_PCM_S16BE; + /* 16 bit form will be handled as CODEC_ID_PCM_S16BE */ + codec_id = CODEC_ID_PCM_DVD; } else if (startcode >= 0xb0 && startcode <= 0xbf) { type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_MLP; @@ -482,6 +498,19 @@ static int mpegps_read_packet(AVFormatContext *s, } else if (startcode >= 0xfd55 && startcode <= 0xfd5f) { type = CODEC_TYPE_VIDEO; codec_id = CODEC_ID_VC1; + } else if (startcode == 0x1bd) { + // check dvd audio substream type + type = CODEC_TYPE_AUDIO; + switch(dvdaudio_substream_type & 0xe0) { + case 0xa0: codec_id = CODEC_ID_PCM_DVD; + break; + case 0x80: if((dvdaudio_substream_type & 0xf8) == 0x88) + codec_id = CODEC_ID_DTS; + else codec_id = CODEC_ID_AC3; + break; + default: av_log(s, AV_LOG_ERROR, "Unknown 0x1bd sub-stream\n"); + goto skip; + } } else { skip: /* skip packet */ @@ -499,7 +528,8 @@ static int mpegps_read_packet(AVFormatContext *s, found: if(st->discard >= AVDISCARD_ALL) goto skip; - if (startcode >= 0xa0 && startcode <= 0xaf) { + if ((startcode >= 0xa0 && startcode <= 0xaf) || + (startcode == 0x1bd && ((dvdaudio_substream_type & 0xe0) == 0xa0))) { int b1, freq; /* for LPCM, we just skip the header and consider it is raw @@ -513,7 +543,14 @@ static int mpegps_read_packet(AVFormatContext *s, freq = (b1 >> 4) & 3; st->codec->sample_rate = lpcm_freq_tab[freq]; st->codec->channels = 1 + (b1 & 7); - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2; + st->codec->bits_per_coded_sample = 16 + ((b1 >> 6) & 3) * 4; + st->codec->bit_rate = st->codec->channels * + st->codec->sample_rate * + st->codec->bits_per_coded_sample; + if (st->codec->bits_per_coded_sample == 16) + st->codec->codec_id = CODEC_ID_PCM_S16BE; + else if (st->codec->bits_per_coded_sample == 28) + return AVERROR(EINVAL); } av_new_packet(pkt, len); get_buffer(s->pb, pkt->data, pkt->size); @@ -528,11 +565,6 @@ static int mpegps_read_packet(AVFormatContext *s, return 0; } -static int mpegps_read_close(AVFormatContext *s) -{ - return 0; -} - static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit) { @@ -543,7 +575,9 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, #ifdef DEBUG_SEEK printf("read_dts: pos=0x%"PRIx64" next=%d -> ", pos, find_next); #endif - url_fseek(s->pb, pos, SEEK_SET); + if (url_fseek(s->pb, pos, SEEK_SET) < 0) + return AV_NOPTS_VALUE; + for(;;) { len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); if (len < 0) { @@ -567,13 +601,13 @@ static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, AVInputFormat mpegps_demuxer = { "mpeg", - "MPEG PS format", + NULL_IF_CONFIG_SMALL("MPEG-PS format"), sizeof(MpegDemuxContext), mpegps_probe, mpegps_read_header, mpegps_read_packet, - mpegps_read_close, + NULL, NULL, //mpegps_read_seek, mpegps_read_dts, - .flags = AVFMT_SHOW_IDS, + .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT, };