X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmpeg.c;h=a0b8f595764b3b39e17cadac26911b07865d73ec;hb=6c071a2b389578b0607b4d4356520a43fac4b3bc;hp=6ba516370f7a66095b5ed74c64912329be7b4c13;hpb=245159265267f0636142114cef3ea33b26e99510;p=ffmpeg diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index 6ba516370f7..a0b8f595764 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -1,1023 +1,143 @@ /* - * MPEG1/2 mux/demux - * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. + * MPEG1/2 demuxer + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * - * This library is free software; you can redistribute it and/or + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avformat.h" -#define MAX_PAYLOAD_SIZE 4096 -//#define DEBUG_SEEK +#include "avformat.h" +#include "internal.h" +#include "mpeg.h" #undef NDEBUG #include -typedef struct { - uint8_t buffer[MAX_PAYLOAD_SIZE]; - int buffer_ptr; - int nb_frames; /* number of starting frame encountered (AC3) */ - int frame_start_offset; /* starting offset of the frame + 1 (0 if none) */ - uint8_t id; - int max_buffer_size; /* in bytes */ - int packet_number; - int64_t start_pts; - int64_t start_dts; - uint8_t lpcm_header[3]; - int lpcm_align; -} StreamInfo; - -typedef struct { - int packet_size; /* required packet size */ - int packet_number; - int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */ - int system_header_freq; - int system_header_size; - int mux_rate; /* bitrate in units of 50 bytes/s */ - /* stream info */ - int audio_bound; - int video_bound; - int is_mpeg2; - int is_vcd; - int is_svcd; - int scr_stream_index; /* stream from which the system clock is - computed (VBR case) */ - int64_t last_scr; /* current system clock */ - - double vcd_padding_bitrate; - int64_t vcd_padding_bytes_written; - -} MpegMuxContext; - -#define PACK_START_CODE ((unsigned int)0x000001ba) -#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb) -#define SEQUENCE_END_CODE ((unsigned int)0x000001b7) -#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00) -#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100) -#define ISO_11172_END_CODE ((unsigned int)0x000001b9) - -/* mpeg2 */ -#define PROGRAM_STREAM_MAP 0x1bc -#define PRIVATE_STREAM_1 0x1bd -#define PADDING_STREAM 0x1be -#define PRIVATE_STREAM_2 0x1bf - - -#define AUDIO_ID 0xc0 -#define VIDEO_ID 0xe0 -#define AC3_ID 0x80 -#define LPCM_ID 0xa0 - -static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 }; - -#ifdef CONFIG_ENCODERS -extern AVOutputFormat mpeg1system_mux; -extern AVOutputFormat mpeg1vcd_mux; -extern AVOutputFormat mpeg2vob_mux; -extern AVOutputFormat mpeg2svcd_mux; - -static int put_pack_header(AVFormatContext *ctx, - uint8_t *buf, int64_t timestamp) -{ - MpegMuxContext *s = ctx->priv_data; - PutBitContext pb; - - init_put_bits(&pb, buf, 128); - - put_bits(&pb, 32, PACK_START_CODE); - if (s->is_mpeg2) { - put_bits(&pb, 2, 0x1); - } else { - put_bits(&pb, 4, 0x2); - } - put_bits(&pb, 3, (uint32_t)((timestamp >> 30) & 0x07)); - put_bits(&pb, 1, 1); - put_bits(&pb, 15, (uint32_t)((timestamp >> 15) & 0x7fff)); - put_bits(&pb, 1, 1); - put_bits(&pb, 15, (uint32_t)((timestamp) & 0x7fff)); - put_bits(&pb, 1, 1); - if (s->is_mpeg2) { - /* clock extension */ - put_bits(&pb, 9, 0); - } - put_bits(&pb, 1, 1); - put_bits(&pb, 22, s->mux_rate); - put_bits(&pb, 1, 1); - if (s->is_mpeg2) { - put_bits(&pb, 1, 1); - put_bits(&pb, 5, 0x1f); /* reserved */ - put_bits(&pb, 3, 0); /* stuffing length */ - } - flush_put_bits(&pb); - return pbBufPtr(&pb) - pb.buf; -} - -static int put_system_header(AVFormatContext *ctx, uint8_t *buf,int only_for_stream_id) -{ - MpegMuxContext *s = ctx->priv_data; - int size, rate_bound, i, private_stream_coded, id; - PutBitContext pb; - - init_put_bits(&pb, buf, 128); - - put_bits(&pb, 32, SYSTEM_HEADER_START_CODE); - put_bits(&pb, 16, 0); - put_bits(&pb, 1, 1); - - rate_bound = s->mux_rate; /* maximum bit rate of the multiplexed stream */ - put_bits(&pb, 22, rate_bound); - put_bits(&pb, 1, 1); /* marker */ - if (s->is_vcd && only_for_stream_id==VIDEO_ID) { - /* This header applies only to the video stream (see VCD standard p. IV-7)*/ - put_bits(&pb, 6, 0); - } else - put_bits(&pb, 6, s->audio_bound); - - if (s->is_vcd) - put_bits(&pb, 1, 0); /* see VCD standard, p. IV-7*/ - else - put_bits(&pb, 1, 1); /* variable bitrate*/ - put_bits(&pb, 1, 1); /* non constrainted bit stream */ - - if (s->is_vcd) { - /* see VCD standard p IV-7 */ - put_bits(&pb, 1, 1); /* audio locked */ - put_bits(&pb, 1, 1); /* video locked */ - } else { - put_bits(&pb, 1, 0); /* audio locked */ - put_bits(&pb, 1, 0); /* video locked */ - } - - put_bits(&pb, 1, 1); /* marker */ - - if (s->is_vcd && only_for_stream_id==AUDIO_ID) { - /* This header applies only to the audio stream (see VCD standard p. IV-7)*/ - put_bits(&pb, 5, 0); - } else - put_bits(&pb, 5, s->video_bound); - - put_bits(&pb, 8, 0xff); /* reserved byte */ - - /* audio stream info */ - private_stream_coded = 0; - for(i=0;inb_streams;i++) { - StreamInfo *stream = ctx->streams[i]->priv_data; - - /* For VCDs, only include the stream info for the stream - that the pack which contains this system belongs to. - (see VCD standard p. IV-7) */ - if ( !s->is_vcd || stream->id==only_for_stream_id - || only_for_stream_id==0) { - - id = stream->id; - if (id < 0xc0) { - /* special case for private streams (AC3 use that) */ - if (private_stream_coded) - continue; - private_stream_coded = 1; - id = 0xbd; - } - put_bits(&pb, 8, id); /* stream ID */ - put_bits(&pb, 2, 3); - if (id < 0xe0) { - /* audio */ - put_bits(&pb, 1, 0); - put_bits(&pb, 13, stream->max_buffer_size / 128); - } else { - /* video */ - put_bits(&pb, 1, 1); - put_bits(&pb, 13, stream->max_buffer_size / 1024); - } - } - } - flush_put_bits(&pb); - size = pbBufPtr(&pb) - pb.buf; - /* patch packet size */ - buf[4] = (size - 6) >> 8; - buf[5] = (size - 6) & 0xff; - - return size; -} - -static int get_system_header_size(AVFormatContext *ctx) -{ - int buf_index, i, private_stream_coded; - StreamInfo *stream; - - buf_index = 12; - private_stream_coded = 0; - for(i=0;inb_streams;i++) { - stream = ctx->streams[i]->priv_data; - if (stream->id < 0xc0) { - if (private_stream_coded) - continue; - private_stream_coded = 1; - } - buf_index += 3; - } - return buf_index; -} - -static int mpeg_mux_init(AVFormatContext *ctx) -{ - MpegMuxContext *s = ctx->priv_data; - int bitrate, i, mpa_id, mpv_id, ac3_id, lpcm_id, j; - AVStream *st; - StreamInfo *stream; - int audio_bitrate; - int video_bitrate; - - s->packet_number = 0; - s->is_vcd = (ctx->oformat == &mpeg1vcd_mux); - s->is_svcd = (ctx->oformat == &mpeg2svcd_mux); - s->is_mpeg2 = (ctx->oformat == &mpeg2vob_mux || ctx->oformat == &mpeg2svcd_mux); - - if (s->is_vcd || s->is_svcd) - s->packet_size = 2324; /* VCD/SVCD packet size */ - else - s->packet_size = 2048; - - s->vcd_padding_bytes_written = 0; - s->vcd_padding_bitrate=0; - - s->audio_bound = 0; - s->video_bound = 0; - mpa_id = AUDIO_ID; - ac3_id = AC3_ID; - mpv_id = VIDEO_ID; - lpcm_id = LPCM_ID; - s->scr_stream_index = -1; - for(i=0;inb_streams;i++) { - st = ctx->streams[i]; - stream = av_mallocz(sizeof(StreamInfo)); - if (!stream) - goto fail; - st->priv_data = stream; - - switch(st->codec.codec_type) { - case CODEC_TYPE_AUDIO: - if (st->codec.codec_id == CODEC_ID_AC3) { - stream->id = ac3_id++; - } else if (st->codec.codec_id == CODEC_ID_PCM_S16BE) { - stream->id = lpcm_id++; - for(j = 0; j < 4; j++) { - if (lpcm_freq_tab[j] == st->codec.sample_rate) - break; - } - if (j == 4) - goto fail; - if (st->codec.channels > 8) - return -1; - stream->lpcm_header[0] = 0x0c; - stream->lpcm_header[1] = (st->codec.channels - 1) | (j << 4); - stream->lpcm_header[2] = 0x80; - stream->lpcm_align = st->codec.channels * 2; - } else { - stream->id = mpa_id++; - } - stream->max_buffer_size = 4 * 1024; - s->audio_bound++; - break; - case CODEC_TYPE_VIDEO: - /* by default, video is used for the SCR computation */ - if (s->scr_stream_index == -1) - s->scr_stream_index = i; - stream->id = mpv_id++; - stream->max_buffer_size = 46 * 1024; - s->video_bound++; - break; - default: - av_abort(); - } - } - /* if no SCR, use first stream (audio) */ - if (s->scr_stream_index == -1) - s->scr_stream_index = 0; - - bitrate = 0; - audio_bitrate = 0; - video_bitrate = 0; - for(i=0;inb_streams;i++) { - st = ctx->streams[i]; - stream = (StreamInfo*) st->priv_data; - - bitrate += st->codec.bit_rate; - - if (stream->id==AUDIO_ID) - audio_bitrate += st->codec.bit_rate; - else if (stream->id==VIDEO_ID) - video_bitrate += st->codec.bit_rate; - } - - if (s->is_vcd) { - double overhead_rate; - - /* The VCD standard mandates that the mux_rate field is 3528 - (see standard p. IV-6). - The value is actually "wrong", i.e. if you calculate - it using the normal formula and the 75 sectors per second transfer - rate you get a different value because the real pack size is 2324, - not 2352. But the standard explicitly specifies that the mux_rate - field in the header must have this value.*/ - s->mux_rate=2352 * 75 / 50; /* = 3528*/ - - /* The VCD standard states that the muxed stream must be - exactly 75 packs / second (the data rate of a single speed cdrom). - Since the video bitrate (probably 1150000 bits/sec) will be below - the theoretical maximum we have to add some padding packets - to make up for the lower data rate. - (cf. VCD standard p. IV-6 )*/ - - /* Add the header overhead to the data rate. - 2279 data bytes per audio pack, 2294 data bytes per video pack*/ - overhead_rate = ((audio_bitrate / 8.0) / 2279) * (2324 - 2279); - overhead_rate += ((video_bitrate / 8.0) / 2294) * (2324 - 2294); - overhead_rate *= 8; - - /* Add padding so that the full bitrate is 2324*75 bytes/sec */ - s->vcd_padding_bitrate = 2324 * 75 * 8 - (bitrate + overhead_rate); - - } else { - /* we increase slightly the bitrate to take into account the - headers. XXX: compute it exactly */ - bitrate += 2000; - s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50); - } - - if (s->is_vcd || s->is_mpeg2) - /* every packet */ - s->pack_header_freq = 1; - else - /* every 2 seconds */ - s->pack_header_freq = 2 * bitrate / s->packet_size / 8; - - /* the above seems to make pack_header_freq zero sometimes */ - if (s->pack_header_freq == 0) - s->pack_header_freq = 1; - - if (s->is_mpeg2) - /* every 200 packets. Need to look at the spec. */ - s->system_header_freq = s->pack_header_freq * 40; - else if (s->is_vcd) - /* the standard mandates that there are only two system headers - in the whole file: one in the first packet of each stream. - (see standard p. IV-7 and IV-8) */ - s->system_header_freq = 0x7fffffff; - else - s->system_header_freq = s->pack_header_freq * 5; - - for(i=0;inb_streams;i++) { - stream = ctx->streams[i]->priv_data; - stream->buffer_ptr = 0; - stream->packet_number = 0; - stream->start_pts = AV_NOPTS_VALUE; - stream->start_dts = AV_NOPTS_VALUE; - } - s->system_header_size = get_system_header_size(ctx); - s->last_scr = 0; - return 0; - fail: - for(i=0;inb_streams;i++) { - av_free(ctx->streams[i]->priv_data); - } - return -ENOMEM; -} - -static inline void put_timestamp(ByteIOContext *pb, int id, int64_t timestamp) -{ - put_byte(pb, - (id << 4) | - (((timestamp >> 30) & 0x07) << 1) | - 1); - put_be16(pb, (uint16_t)((((timestamp >> 15) & 0x7fff) << 1) | 1)); - put_be16(pb, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1)); -} - - -/* return the number of padding bytes that should be inserted into - the multiplexed stream.*/ -static int get_vcd_padding_size(AVFormatContext *ctx, int64_t pts) -{ - MpegMuxContext *s = ctx->priv_data; - int pad_bytes = 0; - - if (s->vcd_padding_bitrate > 0 && pts!=AV_NOPTS_VALUE) - { - int64_t full_pad_bytes; - - full_pad_bytes = (int64_t)((s->vcd_padding_bitrate * (pts / 90000.0)) / 8.0); - pad_bytes = (int) (full_pad_bytes - s->vcd_padding_bytes_written); - - if (pad_bytes<0) - /* might happen if we have already padded to a later timestamp. This - can occur if another stream has already advanced further.*/ - pad_bytes=0; - } - - return pad_bytes; -} - - -/* return the exact available payload size for the next packet for - stream 'stream_index'. 'pts' and 'dts' are only used to know if - timestamps are needed in the packet header. */ -static int get_packet_payload_size(AVFormatContext *ctx, int stream_index, - int64_t pts, int64_t dts) -{ - MpegMuxContext *s = ctx->priv_data; - int buf_index; - StreamInfo *stream; - - stream = ctx->streams[stream_index]->priv_data; - - buf_index = 0; - if (((s->packet_number % s->pack_header_freq) == 0)) { - /* pack header size */ - if (s->is_mpeg2) - buf_index += 14; - else - buf_index += 12; - - if (s->is_vcd) { - /* there is exactly one system header for each stream in a VCD MPEG, - One in the very first video packet and one in the very first - audio packet (see VCD standard p. IV-7 and IV-8).*/ - - if (stream->packet_number==0) - /* The system headers refer only to the stream they occur in, - so they have a constant size.*/ - buf_index += 15; - - } else { - if ((s->packet_number % s->system_header_freq) == 0) - buf_index += s->system_header_size; - } - } - - if (s->is_vcd && stream->packet_number==0) - /* the first pack of each stream contains only the pack header, - the system header and some padding (see VCD standard p. IV-6) - Add the padding size, so that the actual payload becomes 0.*/ - buf_index += s->packet_size - buf_index; - else { - /* packet header size */ - buf_index += 6; - if (s->is_mpeg2) - buf_index += 3; - if (pts != AV_NOPTS_VALUE) { - if (dts != pts) - buf_index += 5 + 5; - else - buf_index += 5; - - } else { - if (!s->is_mpeg2) - buf_index++; - } - - if (stream->id < 0xc0) { - /* AC3/LPCM private data header */ - buf_index += 4; - if (stream->id >= 0xa0) { - int n; - buf_index += 3; - /* NOTE: we round the payload size to an integer number of - LPCM samples */ - n = (s->packet_size - buf_index) % stream->lpcm_align; - if (n) - buf_index += (stream->lpcm_align - n); - } - } - - if (s->is_vcd && stream->id == AUDIO_ID) - /* The VCD standard demands that 20 zero bytes follow - each audio packet (see standard p. IV-8).*/ - buf_index+=20; - } - return s->packet_size - buf_index; -} - -/* Write an MPEG padding packet header. */ -static int put_padding_header(AVFormatContext *ctx,uint8_t* buf, int full_padding_size) -{ - MpegMuxContext *s = ctx->priv_data; - int size = full_padding_size - 6; /* subtract header length */ - - buf[0] = (uint8_t)(PADDING_STREAM >> 24); - buf[1] = (uint8_t)(PADDING_STREAM >> 16); - buf[2] = (uint8_t)(PADDING_STREAM >> 8); - buf[3] = (uint8_t)(PADDING_STREAM); - buf[4] = (uint8_t)(size >> 8); - buf[5] = (uint8_t)(size & 0xff); - - if (!s->is_mpeg2) { - buf[6] = 0x0f; - return 7; - } else - return 6; -} - -static void put_padding_packet(AVFormatContext *ctx, ByteIOContext *pb,int packet_bytes) -{ - uint8_t buffer[7]; - int size, i; - - size = put_padding_header(ctx,buffer, packet_bytes); - put_buffer(pb, buffer, size); - packet_bytes -= size; - - for(i=0;ipriv_data; - StreamInfo *stream = ctx->streams[stream_index]->priv_data; - uint8_t *buf_ptr; - int size, payload_size, startcode, id, stuffing_size, i, header_len; - int packet_size; - uint8_t buffer[128]; - int zero_trail_bytes = 0; - int pad_packet_bytes = 0; - - id = stream->id; - -#if 0 - printf("packet ID=%2x PTS=%0.3f\n", - id, pts / 90000.0); -#endif - - buf_ptr = buffer; - - if (((s->packet_number % s->pack_header_freq) == 0)) { - /* output pack and systems header if needed */ - size = put_pack_header(ctx, buf_ptr, scr); - buf_ptr += size; - - if (s->is_vcd) { - /* there is exactly one system header for each stream in a VCD MPEG, - One in the very first video packet and one in the very first - audio packet (see VCD standard p. IV-7 and IV-8).*/ - - if (stream->packet_number==0) { - size = put_system_header(ctx, buf_ptr, id); - buf_ptr += size; - } - } else { - if ((s->packet_number % s->system_header_freq) == 0) { - size = put_system_header(ctx, buf_ptr, 0); - buf_ptr += size; - } - } - } - size = buf_ptr - buffer; - put_buffer(&ctx->pb, buffer, size); - - packet_size = s->packet_size - size; - - if (s->is_vcd && id == AUDIO_ID) - /* The VCD standard demands that 20 zero bytes follow - each audio pack (see standard p. IV-8).*/ - zero_trail_bytes += 20; - - if (s->is_vcd && stream->packet_number==0) { - /* the first pack of each stream contains only the pack header, - the system header and lots of padding (see VCD standard p. IV-6). - In the case of an audio pack, 20 zero bytes are also added at - the end.*/ - pad_packet_bytes = packet_size - zero_trail_bytes; - } - - packet_size -= pad_packet_bytes + zero_trail_bytes; - - if (packet_size > 0) { - - /* packet header size */ - packet_size -= 6; - - /* packet header */ - if (s->is_mpeg2) { - header_len = 3; - } else { - header_len = 0; - } - if (pts != AV_NOPTS_VALUE) { - if (dts != pts) - header_len += 5 + 5; - else - header_len += 5; - } else { - if (!s->is_mpeg2) - header_len++; - } - - payload_size = packet_size - header_len; - if (id < 0xc0) { - startcode = PRIVATE_STREAM_1; - payload_size -= 4; - if (id >= 0xa0) - payload_size -= 3; - } else { - startcode = 0x100 + id; - } - - stuffing_size = payload_size - stream->buffer_ptr; - if (stuffing_size < 0) - stuffing_size = 0; - put_be32(&ctx->pb, startcode); - - put_be16(&ctx->pb, packet_size); - - if (!s->is_mpeg2) - for(i=0;ipb, 0xff); - - if (s->is_mpeg2) { - put_byte(&ctx->pb, 0x80); /* mpeg2 id */ - - if (pts != AV_NOPTS_VALUE) { - if (dts != pts) { - put_byte(&ctx->pb, 0xc0); /* flags */ - put_byte(&ctx->pb, header_len - 3 + stuffing_size); - put_timestamp(&ctx->pb, 0x03, pts); - put_timestamp(&ctx->pb, 0x01, dts); - } else { - put_byte(&ctx->pb, 0x80); /* flags */ - put_byte(&ctx->pb, header_len - 3 + stuffing_size); - put_timestamp(&ctx->pb, 0x02, pts); - } - } else { - put_byte(&ctx->pb, 0x00); /* flags */ - put_byte(&ctx->pb, header_len - 3 + stuffing_size); - } - } else { - if (pts != AV_NOPTS_VALUE) { - if (dts != pts) { - put_timestamp(&ctx->pb, 0x03, pts); - put_timestamp(&ctx->pb, 0x01, dts); - } else { - put_timestamp(&ctx->pb, 0x02, pts); - } - } else { - put_byte(&ctx->pb, 0x0f); - } - } - - if (startcode == PRIVATE_STREAM_1) { - put_byte(&ctx->pb, id); - if (id >= 0xa0) { - /* LPCM (XXX: check nb_frames) */ - put_byte(&ctx->pb, 7); - put_be16(&ctx->pb, 4); /* skip 3 header bytes */ - put_byte(&ctx->pb, stream->lpcm_header[0]); - put_byte(&ctx->pb, stream->lpcm_header[1]); - put_byte(&ctx->pb, stream->lpcm_header[2]); - } else { - /* AC3 */ - put_byte(&ctx->pb, stream->nb_frames); - put_be16(&ctx->pb, stream->frame_start_offset); - } - } - - if (s->is_mpeg2) - for(i=0;ipb, 0xff); - - /* output data */ - put_buffer(&ctx->pb, stream->buffer, payload_size - stuffing_size); - } - - if (pad_packet_bytes > 0) - put_padding_packet(ctx,&ctx->pb, pad_packet_bytes); - - for(i=0;ipb, 0x00); - - put_flush_packet(&ctx->pb); - - s->packet_number++; - stream->packet_number++; - stream->nb_frames = 0; - stream->frame_start_offset = 0; -} - -static void put_vcd_padding_sector(AVFormatContext *ctx) -{ - /* There are two ways to do this padding: writing a sector/pack - of 0 values, or writing an MPEG padding pack. Both seem to - work with most decoders, BUT the VCD standard only allows a 0-sector - (see standard p. IV-4, IV-5). - So a 0-sector it is...*/ - - MpegMuxContext *s = ctx->priv_data; - int i; - - for(i=0;ipacket_size;i++) - put_byte(&ctx->pb, 0); - - s->vcd_padding_bytes_written += s->packet_size; - - put_flush_packet(&ctx->pb); - - /* increasing the packet number is correct. The SCR of the following packs - is calculated from the packet_number and it has to include the padding - sector (it represents the sector index, not the MPEG pack index) - (see VCD standard p. IV-6)*/ - s->packet_number++; -} +/*********************************************/ +/* demux code */ -/* XXX: move that to upper layer */ -/* XXX: we assume that there are always 'max_b_frames' between - reference frames. A better solution would be to use the AVFrame pts - field */ -static void compute_pts_dts(AVStream *st, int64_t *ppts, int64_t *pdts, - int64_t timestamp) -{ - int frame_delay; - int64_t pts, dts; +#define MAX_SYNC_SIZE 100000 - if (st->codec.codec_type == CODEC_TYPE_VIDEO && - st->codec.max_b_frames != 0) { - frame_delay = (st->codec.frame_rate_base * 90000LL) / - st->codec.frame_rate; - if (timestamp == 0) { - /* specific case for first frame : DTS just before */ - pts = timestamp; - dts = timestamp - frame_delay; - } else { - timestamp -= frame_delay; - if (st->codec.coded_frame->pict_type == FF_B_TYPE) { - /* B frames has identical pts/dts */ - pts = timestamp; - dts = timestamp; - } else { - /* a reference frame has a pts equal to the dts of the - _next_ one */ - dts = timestamp; - pts = timestamp + (st->codec.max_b_frames + 1) * frame_delay; - } - } -#if 1 - printf("pts=%0.3f dts=%0.3f pict_type=%c\n", - pts / 90000.0, dts / 90000.0, - av_get_pict_type_char(st->codec.coded_frame->pict_type)); -#endif - } else { - pts = timestamp; - dts = timestamp; - } - *ppts = pts & ((1LL << 33) - 1); - *pdts = dts & ((1LL << 33) - 1); +static int check_pes(uint8_t *p, uint8_t *end){ + int pes1; + int pes2= (p[3] & 0xC0) == 0x80 + && (p[4] & 0xC0) != 0x40 + &&((p[4] & 0xC0) == 0x00 || (p[4]&0xC0)>>2 == (p[6]&0xF0)); + + for(p+=3; ppriv_data; - int64_t scr; - - if (s->is_vcd) - /* Since the data delivery rate is constant, SCR is computed - using the formula C + i * 1200 where C is the start constant - and i is the pack index. - It is recommended that SCR 0 is at the beginning of the VCD front - margin (a sequence of empty Form 2 sectors on the CD). - It is recommended that the front margin is 30 sectors long, so - we use C = 30*1200 = 36000 - (Note that even if the front margin is not 30 sectors the file - will still be correct according to the standard. It just won't have - the "recommended" value).*/ - scr = 36000 + s->packet_number * 1200; - else { - /* XXX I believe this calculation of SCR is wrong. SCR - specifies at which time the data should enter the decoder. - Two packs cannot enter the decoder at the same time. */ - - /* XXX: system clock should be computed precisely, especially for - CBR case. The current mode gives at least something coherent */ - if (stream_index == s->scr_stream_index - && pts != AV_NOPTS_VALUE) - scr = pts; - else - scr = s->last_scr; - } - - s->last_scr=scr; - - return scr; -} - - -static int mpeg_mux_write_packet(AVFormatContext *ctx, int stream_index, - const uint8_t *buf, int size, - int64_t timestamp) -{ - MpegMuxContext *s = ctx->priv_data; - AVStream *st = ctx->streams[stream_index]; - StreamInfo *stream = st->priv_data; - int64_t pts, dts, new_start_pts, new_start_dts; - int len, avail_size; - - compute_pts_dts(st, &pts, &dts, timestamp); - - -#if 0 - update_scr(ctx,stream_index,pts); - - printf("%d: pts=%0.3f dts=%0.3f scr=%0.3f\n", - stream_index, - pts / 90000.0, - dts / 90000.0, - s->last_scr / 90000.0); -#endif - - /* we assume here that pts != AV_NOPTS_VALUE */ - new_start_pts = stream->start_pts; - new_start_dts = stream->start_dts; - - if (stream->start_pts == AV_NOPTS_VALUE) { - new_start_pts = pts; - new_start_dts = dts; - } - avail_size = get_packet_payload_size(ctx, stream_index, - new_start_pts, - new_start_dts); - if (stream->buffer_ptr >= avail_size) { - - update_scr(ctx,stream_index,stream->start_pts); - - /* unlikely case: outputing the pts or dts increase the packet - size so that we cannot write the start of the next - packet. In this case, we must flush the current packet with - padding. - Note: this always happens for the first audio and video packet - in a VCD file, since they do not carry any data.*/ - flush_packet(ctx, stream_index, - stream->start_pts, stream->start_dts, s->last_scr); - stream->buffer_ptr = 0; - } - stream->start_pts = new_start_pts; - stream->start_dts = new_start_dts; - stream->nb_frames++; - if (stream->frame_start_offset == 0) - stream->frame_start_offset = stream->buffer_ptr; - while (size > 0) { - avail_size = get_packet_payload_size(ctx, stream_index, - stream->start_pts, - stream->start_dts); - len = avail_size - stream->buffer_ptr; - if (len > size) - len = size; - memcpy(stream->buffer + stream->buffer_ptr, buf, len); - stream->buffer_ptr += len; - buf += len; - size -= len; - if (stream->buffer_ptr >= avail_size) { - - update_scr(ctx,stream_index,stream->start_pts); - - /* if packet full, we send it now */ - flush_packet(ctx, stream_index, - stream->start_pts, stream->start_dts, s->last_scr); - stream->buffer_ptr = 0; - - if (s->is_vcd) { - /* Write one or more padding sectors, if necessary, to reach - the constant overall bitrate.*/ - int vcd_pad_bytes; - - while((vcd_pad_bytes = get_vcd_padding_size(ctx,stream->start_pts) ) >= s->packet_size) - put_vcd_padding_sector(ctx); - } - - /* Make sure only the FIRST pes packet for this frame has - a timestamp */ - stream->start_pts = AV_NOPTS_VALUE; - stream->start_dts = AV_NOPTS_VALUE; - } - } - - return 0; +static int check_pack_header(const uint8_t *buf) { + return (buf[1] & 0xC0) == 0x40 || (buf[1] & 0xF0) == 0x20; } -static int mpeg_mux_end(AVFormatContext *ctx) +static int mpegps_probe(AVProbeData *p) { - MpegMuxContext *s = ctx->priv_data; - StreamInfo *stream; + uint32_t code= -1; + int sys=0, pspack=0, priv1=0, vid=0, audio=0, invalid=0; int i; + int score=0; - /* flush each packet */ - for(i=0;inb_streams;i++) { - stream = ctx->streams[i]->priv_data; - if (stream->buffer_ptr > 0) { - update_scr(ctx,i,stream->start_pts); - - /* NOTE: we can always write the remaining data as it was - tested before in mpeg_mux_write_packet() */ - flush_packet(ctx, i, stream->start_pts, stream->start_dts, - s->last_scr); + for(i=0; ibuf_size; i++){ + code = (code<<8) + p->buf[i]; + if ((code & 0xffffff00) == 0x100) { + int len= p->buf[i+1] << 8 | p->buf[i+2]; + int pes= check_pes(p->buf+i, p->buf+p->buf_size); + int pack = check_pack_header(p->buf+i); + + if(code == SYSTEM_HEADER_START_CODE) sys++; + else if(code == PACK_START_CODE && pack) pspack++; + else if((code & 0xf0) == VIDEO_ID && pes) vid++; + // skip pes payload to avoid start code emulation for private + // and audio streams + else if((code & 0xe0) == AUDIO_ID && pes) {audio++; i+=len;} + else if(code == PRIVATE_STREAM_1 && pes) {priv1++; i+=len;} + + else if((code & 0xf0) == VIDEO_ID && !pes) invalid++; + else if((code & 0xe0) == AUDIO_ID && !pes) invalid++; + else if(code == PRIVATE_STREAM_1 && !pes) invalid++; } } - /* End header according to MPEG1 systems standard. We do not write - it as it is usually not needed by decoders and because it - complicates MPEG stream concatenation. */ - //put_be32(&ctx->pb, ISO_11172_END_CODE); - //put_flush_packet(&ctx->pb); + if(vid+audio > invalid) /* invalid VDR files nd short PES streams */ + score= AVPROBE_SCORE_MAX/4; - for(i=0;inb_streams;i++) - av_freep(&ctx->streams[i]->priv_data); +//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d %d len:%d\n", sys, priv1, pspack,vid, audio, invalid, p->buf_size); + if(sys>invalid && sys*9 <= pspack*10) + return pspack > 2 ? AVPROBE_SCORE_MAX/2+2 : AVPROBE_SCORE_MAX/4; // +1 for .mpg + if(pspack > invalid && (priv1+vid+audio)*10 >= pspack*9) + return pspack > 2 ? AVPROBE_SCORE_MAX/2+2 : AVPROBE_SCORE_MAX/4; // +1 for .mpg + if((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys && !pspack && p->buf_size>2048 && vid + audio > invalid) /* PES stream */ + return (audio > 12 || vid > 3) ? AVPROBE_SCORE_MAX/2+2 : AVPROBE_SCORE_MAX/4; - return 0; -} -#endif //CONFIG_ENCODERS - -/*********************************************/ -/* demux code */ - -#define MAX_SYNC_SIZE 100000 - -static int mpegps_probe(AVProbeData *p) -{ - int code, c, i; - - code = 0xff; - /* we search the first start code. If it is a packet start code, - then we decide it is mpeg ps. We do not send highest value to - give a chance to mpegts */ - /* NOTE: the search range was restricted to avoid too many false - detections */ - - if (p->buf_size < 6) - return 0; - - for (i = 0; i < 20; i++) { - c = p->buf[i]; - code = (code << 8) | c; - if ((code & 0xffffff00) == 0x100) { - if (code == PACK_START_CODE || - code == SYSTEM_HEADER_START_CODE || - (code >= 0x1e0 && code <= 0x1ef) || - (code >= 0x1c0 && code <= 0x1df) || - code == PRIVATE_STREAM_2 || - code == PROGRAM_STREAM_MAP || - code == PRIVATE_STREAM_1 || - code == PADDING_STREAM) - return AVPROBE_SCORE_MAX - 2; - else - return 0; - } - } - return 0; + //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1 + //mp3_misidentified_2.mp3 has sys:0 priv1:0 pspack:0 vid:0 audio:6 + return score; } typedef struct MpegDemuxContext { - int header_state; + int32_t header_state; + unsigned char psm_es_type[256]; + int sofdec; } MpegDemuxContext; -static int mpegps_read_header(AVFormatContext *s, - AVFormatParameters *ap) +static int mpegps_read_header(AVFormatContext *s) { MpegDemuxContext *m = s->priv_data; + const char *sofdec = "Sofdec"; + int v, i = 0; + m->header_state = 0xff; s->ctx_flags |= AVFMTCTX_NOHEADER; + m->sofdec = -1; + do { + v = avio_r8(s->pb); + m->header_state = m->header_state << 8 | v; + m->sofdec++; + } while (v == sofdec[i] && i++ < 6); + + m->sofdec = (m->sofdec == 6) ? 1 : 0; + /* no need to do more */ return 0; } -static int64_t get_pts(ByteIOContext *pb, int c) +static int64_t get_pts(AVIOContext *pb, int c) { - int64_t pts; - int val; + uint8_t buf[5]; + + buf[0] = c<0 ? avio_r8(pb) : c; + avio_read(pb, buf+1, 4); - if (c < 0) - c = get_byte(pb); - pts = (int64_t)((c >> 1) & 0x07) << 30; - val = get_be16(pb); - pts |= (int64_t)(val >> 1) << 15; - val = get_be16(pb); - pts |= (int64_t)(val >> 1); - return pts; + return ff_parse_pes_pts(buf); } -static int find_next_start_code(ByteIOContext *pb, int *size_ptr, - uint32_t *header_state) +static int find_next_start_code(AVIOContext *pb, int *size_ptr, + int32_t *header_state) { unsigned int state, v; int val, n; @@ -1025,9 +145,9 @@ static int find_next_start_code(ByteIOContext *pb, int *size_ptr, state = *header_state; n = *size_ptr; while (n > 0) { - if (url_feof(pb)) + if (pb->eof_reached) break; - v = get_byte(pb); + v = avio_r8(pb); n--; if (state == 0x000001) { state = ((state << 8) | v) & 0xffffff; @@ -1043,173 +163,213 @@ static int find_next_start_code(ByteIOContext *pb, int *size_ptr, return val; } -/* XXX: optimize */ -static int find_prev_start_code(ByteIOContext *pb, int *size_ptr) +/** + * Extract stream types from a program stream map + * According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35 + * + * @return number of bytes occupied by PSM in the bitstream + */ +static long mpegps_psm_parse(MpegDemuxContext *m, AVIOContext *pb) { - int64_t pos, pos_start; - int max_size, start_code; - - max_size = *size_ptr; - pos_start = url_ftell(pb); - - /* in order to go faster, we fill the buffer */ - pos = pos_start - 16386; - if (pos < 0) - pos = 0; - url_fseek(pb, pos, SEEK_SET); - get_byte(pb); - - pos = pos_start; - for(;;) { - pos--; - if (pos < 0 || (pos_start - pos) >= max_size) { - start_code = -1; - goto the_end; - } - url_fseek(pb, pos, SEEK_SET); - start_code = get_be32(pb); - if ((start_code & 0xffffff00) == 0x100) - break; - } - the_end: - *size_ptr = pos_start - pos; - return start_code; + int psm_length, ps_info_length, es_map_length; + + psm_length = avio_rb16(pb); + avio_r8(pb); + avio_r8(pb); + ps_info_length = avio_rb16(pb); + + /* skip program_stream_info */ + avio_skip(pb, ps_info_length); + es_map_length = avio_rb16(pb); + + /* at least one es available? */ + while (es_map_length >= 4){ + unsigned char type = avio_r8(pb); + unsigned char es_id = avio_r8(pb); + uint16_t es_info_length = avio_rb16(pb); + /* remember mapping from stream id to stream type */ + m->psm_es_type[es_id] = type; + /* skip program_stream_info */ + avio_skip(pb, es_info_length); + es_map_length -= 4 + es_info_length; + } + avio_rb32(pb); /* crc32 */ + return 2 + psm_length; } -/* read the next (or previous) PES header. Return its position in ppos +/* read the next PES header. Return its position in ppos (if not NULL), and its start code, pts and dts. */ static int mpegps_read_pes_header(AVFormatContext *s, - int64_t *ppos, int *pstart_code, - int64_t *ppts, int64_t *pdts, int find_next) + int64_t *ppos, int *pstart_code, + int64_t *ppts, int64_t *pdts) { MpegDemuxContext *m = s->priv_data; int len, size, startcode, c, flags, header_len; - int64_t pts, dts, last_pos; + int pes_ext, ext2_len, id_ext, skip; + int64_t pts, dts; + int64_t last_sync= avio_tell(s->pb); - last_pos = -1; + error_redo: + avio_seek(s->pb, last_sync, SEEK_SET); redo: - if (find_next) { /* next start code (should be immediately after) */ m->header_state = 0xff; size = MAX_SYNC_SIZE; - startcode = find_next_start_code(&s->pb, &size, &m->header_state); - } else { - if (last_pos >= 0) - url_fseek(&s->pb, last_pos, SEEK_SET); - size = MAX_SYNC_SIZE; - startcode = find_prev_start_code(&s->pb, &size); - last_pos = url_ftell(&s->pb) - 4; + startcode = find_next_start_code(s->pb, &size, &m->header_state); + last_sync = avio_tell(s->pb); + //printf("startcode=%x pos=0x%"PRIx64"\n", startcode, avio_tell(s->pb)); + if (startcode < 0){ + if(s->pb->eof_reached) + return AVERROR_EOF; + //FIXME we should remember header_state + return AVERROR(EAGAIN); } - //printf("startcode=%x pos=0x%Lx\n", startcode, url_ftell(&s->pb)); - if (startcode < 0) - return -EIO; + if (startcode == PACK_START_CODE) goto redo; if (startcode == SYSTEM_HEADER_START_CODE) goto redo; - if (startcode == PADDING_STREAM || - startcode == PRIVATE_STREAM_2) { - /* skip them */ - len = get_be16(&s->pb); - url_fskip(&s->pb, len); + if (startcode == PADDING_STREAM) { + avio_skip(s->pb, avio_rb16(s->pb)); goto redo; } + if (startcode == PRIVATE_STREAM_2) { + len = avio_rb16(s->pb); + if (!m->sofdec) { + while (len-- >= 6) { + if (avio_r8(s->pb) == 'S') { + uint8_t buf[5]; + avio_read(s->pb, buf, sizeof(buf)); + m->sofdec = !memcmp(buf, "ofdec", 5); + len -= sizeof(buf); + break; + } + } + m->sofdec -= !m->sofdec; + } + avio_skip(s->pb, len); + goto redo; + } + if (startcode == PROGRAM_STREAM_MAP) { + mpegps_psm_parse(m, s->pb); + goto redo; + } + /* find matching stream */ if (!((startcode >= 0x1c0 && startcode <= 0x1df) || (startcode >= 0x1e0 && startcode <= 0x1ef) || - (startcode == 0x1bd))) + (startcode == 0x1bd) || (startcode == 0x1fd))) goto redo; if (ppos) { - *ppos = url_ftell(&s->pb) - 4; + *ppos = avio_tell(s->pb) - 4; } - len = get_be16(&s->pb); - pts = AV_NOPTS_VALUE; + len = avio_rb16(s->pb); + pts = dts = AV_NOPTS_VALUE; /* stuffing */ for(;;) { if (len < 1) - goto redo; - c = get_byte(&s->pb); + goto error_redo; + c = avio_r8(s->pb); len--; /* XXX: for mpeg1, should test only bit 7 */ - if (c != 0xff) + if (c != 0xff) break; } if ((c & 0xc0) == 0x40) { /* buffer scale & size */ - if (len < 2) - goto redo; - get_byte(&s->pb); - c = get_byte(&s->pb); + avio_r8(s->pb); + c = avio_r8(s->pb); len -= 2; } - if ((c & 0xf0) == 0x20) { - if (len < 4) - goto redo; - dts = pts = get_pts(&s->pb, c); + if ((c & 0xe0) == 0x20) { + dts = pts = get_pts(s->pb, c); len -= 4; - } else if ((c & 0xf0) == 0x30) { - if (len < 9) - goto redo; - pts = get_pts(&s->pb, c); - dts = get_pts(&s->pb, -1); - len -= 9; + if (c & 0x10){ + dts = get_pts(s->pb, -1); + len -= 5; + } } else if ((c & 0xc0) == 0x80) { /* mpeg 2 PES */ - if ((c & 0x30) != 0) { - /* Encrypted multiplex not handled */ - goto redo; - } - flags = get_byte(&s->pb); - header_len = get_byte(&s->pb); + flags = avio_r8(s->pb); + header_len = avio_r8(s->pb); len -= 2; if (header_len > len) - goto redo; - if ((flags & 0xc0) == 0x80) { - dts = pts = get_pts(&s->pb, -1); - if (header_len < 5) - goto redo; + goto error_redo; + len -= header_len; + if (flags & 0x80) { + dts = pts = get_pts(s->pb, -1); header_len -= 5; - len -= 5; - } if ((flags & 0xc0) == 0xc0) { - pts = get_pts(&s->pb, -1); - dts = get_pts(&s->pb, -1); - if (header_len < 10) - goto redo; - header_len -= 10; - len -= 10; + if (flags & 0x40) { + dts = get_pts(s->pb, -1); + header_len -= 5; + } } - len -= header_len; - while (header_len > 0) { - get_byte(&s->pb); + 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 = avio_r8(s->pb); header_len--; + /* 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; + } + avio_skip(s->pb, skip); + header_len -= skip; + + if (pes_ext & 0x01) { /* PES extension 2 */ + ext2_len = avio_r8(s->pb); + header_len--; + if ((ext2_len & 0x7f) > 0) { + id_ext = avio_r8(s->pb); + if ((id_ext & 0x80) == 0) + startcode = ((startcode & 0xff) << 8) | id_ext; + header_len--; + } + } } + if(header_len < 0) + goto error_redo; + avio_skip(s->pb, header_len); } - if (startcode == 0x1bd) { - if (len < 1) - goto redo; - startcode = get_byte(&s->pb); + else if( c!= 0xf ) + goto redo; + + if (startcode == PRIVATE_STREAM_1 && !m->psm_es_type[startcode & 0xff]) { + startcode = avio_r8(s->pb); len--; - if (startcode >= 0x80 && startcode <= 0xbf) { + if (startcode >= 0x80 && startcode <= 0xcf) { /* audio: skip header */ - if (len < 3) - goto redo; - get_byte(&s->pb); - get_byte(&s->pb); - get_byte(&s->pb); + avio_r8(s->pb); + avio_r8(s->pb); + avio_r8(s->pb); len -= 3; + if (startcode >= 0xb0 && startcode <= 0xbf) { + /* MLP/TrueHD audio has a 4-byte header */ + avio_r8(s->pb); + len--; + } } } + if(len<0) + goto error_redo; if(dts != AV_NOPTS_VALUE && ppos){ int i; for(i=0; inb_streams; i++){ - if(startcode == s->streams[i]->id) { - av_add_index_entry(s->streams[i], *ppos, dts, 0, 0 /* FIXME keyframe? */); + if(startcode == s->streams[i]->id && + s->pb->seekable /* 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? */); } } } - + *pstart_code = startcode; *ppts = pts; *pdts = dts; @@ -1219,330 +379,199 @@ static int mpegps_read_pes_header(AVFormatContext *s, static int mpegps_read_packet(AVFormatContext *s, AVPacket *pkt) { + MpegDemuxContext *m = s->priv_data; AVStream *st; - int len, startcode, i, type, codec_id; + int len, startcode, i, es_type, ret; + enum CodecID codec_id = CODEC_ID_NONE; + enum AVMediaType 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, 1); + len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); if (len < 0) return len; - + + if(startcode == 0x1bd) { + dvdaudio_substream_type = avio_r8(s->pb); + avio_skip(s->pb, 3); + len -= 4; + } + /* now find stream */ for(i=0;inb_streams;i++) { st = s->streams[i]; if (st->id == startcode) goto found; } - if (startcode >= 0x1e0 && startcode <= 0x1ef) { - type = CODEC_TYPE_VIDEO; - codec_id = CODEC_ID_MPEG2VIDEO; + + es_type = m->psm_es_type[startcode & 0xff]; + if(es_type > 0 && es_type != STREAM_TYPE_PRIVATE_DATA){ + if(es_type == STREAM_TYPE_VIDEO_MPEG1){ + codec_id = CODEC_ID_MPEG2VIDEO; + type = AVMEDIA_TYPE_VIDEO; + } else if(es_type == STREAM_TYPE_VIDEO_MPEG2){ + codec_id = CODEC_ID_MPEG2VIDEO; + type = AVMEDIA_TYPE_VIDEO; + } else if(es_type == STREAM_TYPE_AUDIO_MPEG1 || + es_type == STREAM_TYPE_AUDIO_MPEG2){ + codec_id = CODEC_ID_MP3; + type = AVMEDIA_TYPE_AUDIO; + } else if(es_type == STREAM_TYPE_AUDIO_AAC){ + codec_id = CODEC_ID_AAC; + type = AVMEDIA_TYPE_AUDIO; + } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){ + codec_id = CODEC_ID_MPEG4; + type = AVMEDIA_TYPE_VIDEO; + } else if(es_type == STREAM_TYPE_VIDEO_H264){ + codec_id = CODEC_ID_H264; + type = AVMEDIA_TYPE_VIDEO; + } else if(es_type == STREAM_TYPE_AUDIO_AC3){ + codec_id = CODEC_ID_AC3; + type = AVMEDIA_TYPE_AUDIO; + } else { + goto skip; + } + } else if (startcode >= 0x1e0 && startcode <= 0x1ef) { + static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 }; + unsigned char buf[8]; + avio_read(s->pb, buf, 8); + avio_seek(s->pb, -8, SEEK_CUR); + if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1)) + codec_id = CODEC_ID_CAVS; + else + codec_id = CODEC_ID_PROBE; + type = AVMEDIA_TYPE_VIDEO; } else if (startcode >= 0x1c0 && startcode <= 0x1df) { - type = CODEC_TYPE_AUDIO; - codec_id = CODEC_ID_MP2; - } else if (startcode >= 0x80 && startcode <= 0x9f) { - type = CODEC_TYPE_AUDIO; + type = AVMEDIA_TYPE_AUDIO; + codec_id = m->sofdec > 0 ? CODEC_ID_ADPCM_ADX : CODEC_ID_MP2; + } else if (startcode >= 0x80 && startcode <= 0x87) { + type = AVMEDIA_TYPE_AUDIO; + codec_id = CODEC_ID_AC3; + } else if ( ( startcode >= 0x88 && startcode <= 0x8f) + ||( startcode >= 0x98 && startcode <= 0x9f)) { + /* 0x90 - 0x97 is reserved for SDDS in DVD specs */ + type = AVMEDIA_TYPE_AUDIO; + codec_id = CODEC_ID_DTS; + } else if (startcode >= 0xa0 && startcode <= 0xaf) { + type = AVMEDIA_TYPE_AUDIO; + /* 16 bit form will be handled as CODEC_ID_PCM_S16BE */ + codec_id = CODEC_ID_PCM_DVD; + } else if (startcode >= 0xb0 && startcode <= 0xbf) { + type = AVMEDIA_TYPE_AUDIO; + codec_id = CODEC_ID_TRUEHD; + } else if (startcode >= 0xc0 && startcode <= 0xcf) { + /* Used for both AC-3 and E-AC-3 in EVOB files */ + type = AVMEDIA_TYPE_AUDIO; codec_id = CODEC_ID_AC3; - } else if (startcode >= 0xa0 && startcode <= 0xbf) { - type = CODEC_TYPE_AUDIO; - codec_id = CODEC_ID_PCM_S16BE; + } else if (startcode >= 0x20 && startcode <= 0x3f) { + type = AVMEDIA_TYPE_SUBTITLE; + codec_id = CODEC_ID_DVD_SUBTITLE; + } else if (startcode >= 0xfd55 && startcode <= 0xfd5f) { + type = AVMEDIA_TYPE_VIDEO; + codec_id = CODEC_ID_VC1; + } else if (startcode == 0x1bd) { + // check dvd audio substream type + type = AVMEDIA_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 */ - url_fskip(&s->pb, len); + avio_skip(s->pb, len); goto redo; } /* no stream found: add a new stream */ - st = av_new_stream(s, startcode); - if (!st) + st = avformat_new_stream(s, NULL); + if (!st) goto skip; - st->codec.codec_type = type; - st->codec.codec_id = codec_id; + st->id = startcode; + st->codec->codec_type = type; + st->codec->codec_id = codec_id; if (codec_id != CODEC_ID_PCM_S16BE) - st->need_parsing = 1; + st->need_parsing = AVSTREAM_PARSE_FULL; found: - if (startcode >= 0xa0 && startcode <= 0xbf) { + if(st->discard >= AVDISCARD_ALL) + goto skip; + 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 audio data */ if (len <= 3) goto skip; - get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */ - b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */ - get_byte(&s->pb); /* dynamic range control (0x80 = off) */ + avio_r8(s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */ + b1 = avio_r8(s->pb); /* quant (2), freq(2), reserved(1), channels(3) */ + avio_r8(s->pb); /* dynamic range control (0x80 = off) */ len -= 3; 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; - } - av_new_packet(pkt, len); - get_buffer(&s->pb, pkt->data, pkt->size); + st->codec->sample_rate = lpcm_freq_tab[freq]; + st->codec->channels = 1 + (b1 & 7); + 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); + } + ret = av_get_packet(s->pb, pkt, len); pkt->pts = pts; pkt->dts = dts; + pkt->pos = dummy_pos; pkt->stream_index = st->index; -#if 0 - printf("%d: pts=%0.3f dts=%0.3f\n", - pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0); -#endif - return 0; -} + av_dlog(s, "%d: pts=%0.3f dts=%0.3f size=%d\n", + pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, + pkt->size); -static int mpegps_read_close(AVFormatContext *s) -{ - return 0; + return (ret < 0) ? ret : 0; } -static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, - int64_t *ppos, int find_next) +static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, + int64_t *ppos, int64_t pos_limit) { int len, startcode; int64_t pos, pts, dts; pos = *ppos; -#ifdef DEBUG_SEEK - printf("read_dts: pos=0x%llx next=%d -> ", pos, find_next); -#endif - url_fseek(&s->pb, pos, SEEK_SET); + if (avio_seek(s->pb, pos, SEEK_SET) < 0) + return AV_NOPTS_VALUE; + for(;;) { - len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts, find_next); + len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); if (len < 0) { -#ifdef DEBUG_SEEK - printf("none (ret=%d)\n", len); -#endif + av_dlog(s, "none (ret=%d)\n", len); return AV_NOPTS_VALUE; } - if (startcode == s->streams[stream_index]->id && + if (startcode == s->streams[stream_index]->id && dts != AV_NOPTS_VALUE) { break; } - if (find_next) { - url_fskip(&s->pb, len); - } else { - url_fseek(&s->pb, pos, SEEK_SET); - } + avio_skip(s->pb, len); } -#ifdef DEBUG_SEEK - printf("pos=0x%llx dts=0x%llx %0.3f\n", pos, dts, dts / 90000.0); -#endif + av_dlog(s, "pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", + pos, dts, dts / 90000.0); *ppos = pos; return dts; } -static int mpegps_read_seek(AVFormatContext *s, - int stream_index, int64_t timestamp) -{ - int64_t pos_min, pos_max, pos, pos_limit; - int64_t dts_min, dts_max, dts; - int index, no_change; - AVStream *st; - - timestamp = (timestamp * 90000) / AV_TIME_BASE; - -#ifdef DEBUG_SEEK - printf("read_seek: %d %0.3f\n", stream_index, timestamp / 90000.0); -#endif - - /* XXX: find stream_index by looking at the first PES packet found */ - if (stream_index < 0) { - stream_index = av_find_default_stream_index(s); - if (stream_index < 0) - return -1; - } - - dts_max= - dts_min= AV_NOPTS_VALUE; - pos_limit= -1; //gcc falsely says it may be uninitalized - - st= s->streams[stream_index]; - if(st->index_entries){ - AVIndexEntry *e; - - index= av_index_search_timestamp(st, timestamp); - e= &st->index_entries[index]; - if(e->timestamp <= timestamp){ - pos_min= e->pos; - dts_min= e->timestamp; -#ifdef DEBUG_SEEK - printf("unsing cached pos_min=0x%llx dts_min=%0.3f\n", - pos_min,dts_min / 90000.0); -#endif - }else{ - assert(index==0); - } - index++; - if(index < st->nb_index_entries){ - e= &st->index_entries[index]; - assert(e->timestamp >= timestamp); - pos_max= e->pos; - dts_max= e->timestamp; - pos_limit= pos_max - e->min_distance; -#ifdef DEBUG_SEEK - printf("unsing cached pos_max=0x%llx dts_max=%0.3f\n", - pos_max,dts_max / 90000.0); -#endif - } - } - - if(dts_min == AV_NOPTS_VALUE){ - pos_min = 0; - dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1); - if (dts_min == AV_NOPTS_VALUE) { - /* we can reach this case only if no PTS are present in - the whole stream */ - return -1; - } - } - if(dts_max == AV_NOPTS_VALUE){ - pos_max = url_filesize(url_fileno(&s->pb)) - 1; - dts_max = mpegps_read_dts(s, stream_index, &pos_max, 0); - pos_limit= pos_max; - } - - no_change=0; - while (pos_min < pos_limit) { -#ifdef DEBUG_SEEK - printf("pos_min=0x%llx pos_max=0x%llx dts_min=%0.3f dts_max=%0.3f\n", - pos_min, pos_max, - dts_min / 90000.0, dts_max / 90000.0); -#endif - int64_t start_pos; - assert(pos_limit <= pos_max); - - if(no_change==0){ - int64_t approximate_keyframe_distance= pos_max - pos_limit; - // interpolate position (better than dichotomy) - pos = (int64_t)((double)(pos_max - pos_min) * - (double)(timestamp - dts_min) / - (double)(dts_max - dts_min)) + pos_min - approximate_keyframe_distance; - }else if(no_change==1){ - // bisection, if interpolation failed to change min or max pos last time - pos = (pos_min + pos_limit)>>1; - }else{ - // linear search if bisection failed, can only happen if there are very few or no keframes between min/max - pos=pos_min; - } - if(pos <= pos_min) - pos= pos_min + 1; - else if(pos > pos_limit) - pos= pos_limit; - start_pos= pos; - - // read the next timestamp - dts = mpegps_read_dts(s, stream_index, &pos, 1); - if(pos == pos_max) - no_change++; - else - no_change=0; -#ifdef DEBUG_SEEK -printf("%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld noc:%d\n", pos_min, pos, pos_max, dts_min, dts, dts_max, timestamp, pos_limit, start_pos, no_change); -#endif - assert(dts != AV_NOPTS_VALUE); - if (timestamp < dts) { - pos_limit = start_pos - 1; - pos_max = pos; - dts_max = dts; - } else { - pos_min = pos; - dts_min = dts; - /* check if we are lucky */ - if (timestamp == dts) - break; - } - } - - pos = pos_min; -#ifdef DEBUG_SEEK - pos_min = pos; - dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1); - pos_min++; - dts_max = mpegps_read_dts(s, stream_index, &pos_min, 1); - printf("pos=0x%llx %0.3f<=%0.3f<=%0.3f\n", - pos, dts_min / 90000.0, timestamp / 90000.0, dts_max / 90000.0); -#endif - /* do the seek */ - url_fseek(&s->pb, pos, SEEK_SET); - return 0; -} - -#ifdef CONFIG_ENCODERS -static AVOutputFormat mpeg1system_mux = { - "mpeg", - "MPEG1 System format", - "video/mpeg", - "mpg,mpeg", - sizeof(MpegMuxContext), - CODEC_ID_MP2, - CODEC_ID_MPEG1VIDEO, - mpeg_mux_init, - mpeg_mux_write_packet, - mpeg_mux_end, -}; - -static AVOutputFormat mpeg1vcd_mux = { - "vcd", - "MPEG1 System format (VCD)", - "video/mpeg", - NULL, - sizeof(MpegMuxContext), - CODEC_ID_MP2, - CODEC_ID_MPEG1VIDEO, - mpeg_mux_init, - mpeg_mux_write_packet, - mpeg_mux_end, -}; - -static AVOutputFormat mpeg2vob_mux = { - "vob", - "MPEG2 PS format (VOB)", - "video/mpeg", - "vob", - sizeof(MpegMuxContext), - CODEC_ID_MP2, - CODEC_ID_MPEG2VIDEO, - mpeg_mux_init, - mpeg_mux_write_packet, - mpeg_mux_end, -}; - -/* Same as mpeg2vob_mux except that the pack size is 2324 */ -static AVOutputFormat mpeg2svcd_mux = { - "svcd", - "MPEG2 PS format (VOB)", - "video/mpeg", - "vob", - sizeof(MpegMuxContext), - CODEC_ID_MP2, - CODEC_ID_MPEG2VIDEO, - mpeg_mux_init, - mpeg_mux_write_packet, - mpeg_mux_end, +AVInputFormat ff_mpegps_demuxer = { + .name = "mpeg", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-PS (MPEG-2 Program Stream)"), + .priv_data_size = sizeof(MpegDemuxContext), + .read_probe = mpegps_probe, + .read_header = mpegps_read_header, + .read_packet = mpegps_read_packet, + .read_timestamp = mpegps_read_dts, + .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, }; - - - -#endif //CONFIG_ENCODERS - -AVInputFormat mpegps_demux = { - "mpeg", - "MPEG PS format", - sizeof(MpegDemuxContext), - mpegps_probe, - mpegps_read_header, - mpegps_read_packet, - mpegps_read_close, - mpegps_read_seek, -}; - -int mpegps_init(void) -{ -#ifdef CONFIG_ENCODERS - av_register_output_format(&mpeg1system_mux); - av_register_output_format(&mpeg1vcd_mux); - av_register_output_format(&mpeg2vob_mux); - av_register_output_format(&mpeg2svcd_mux); -#endif //CONFIG_ENCODERS - av_register_input_format(&mpegps_demux); - return 0; -}