aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2002-05-20 16:29:40 +0000
committerFabrice Bellard <fabrice@bellard.org>2002-05-20 16:29:40 +0000
commitdb7f1f95acc050bb5ddf62b0008eab8c8305d369 (patch)
tree7e9ac2c7d9ea127cedf30057fc5d6c768e7f1934
parentb9a281db69a1b3e723b1fffa8c9e0c552b2e0ddc (diff)
downloadffmpeg-db7f1f95acc050bb5ddf62b0008eab8c8305d369.tar.gz
suppressed mpeg demux mess - use now dynamic stream creation api
Originally committed as revision 546 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libav/mpeg.c399
1 files changed, 82 insertions, 317 deletions
diff --git a/libav/mpeg.c b/libav/mpeg.c
index f14ce0a2d2..902e6bf9ed 100644
--- a/libav/mpeg.c
+++ b/libav/mpeg.c
@@ -1,6 +1,6 @@
/*
- * Output a MPEG1 multiplexed video/audio stream
- * Copyright (c) 2000 Gerard Lantau.
+ * MPEG1 mux/demux
+ * Copyright (c) 2000, 2001, 2002 Gerard Lantau.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -62,8 +62,6 @@ typedef struct {
#define AUDIO_ID 0xc0
#define VIDEO_ID 0xe0
-static int mpeg_mux_check_packet(AVFormatContext *s, int *size);
-
static int put_pack_header(AVFormatContext *ctx,
UINT8 *buf, INT64 timestamp)
{
@@ -150,15 +148,11 @@ static int put_system_header(AVFormatContext *ctx, UINT8 *buf)
static int mpeg_mux_init(AVFormatContext *ctx)
{
- MpegMuxContext *s;
+ MpegMuxContext *s = ctx->priv_data;
int bitrate, i, mpa_id, mpv_id, ac3_id;
AVStream *st;
StreamInfo *stream;
- s = av_mallocz(sizeof(MpegMuxContext));
- if (!s)
- return -1;
- ctx->priv_data = s;
s->packet_number = 0;
/* XXX: hardcoded */
@@ -252,7 +246,6 @@ static int mpeg_mux_init(AVFormatContext *ctx)
for(i=0;i<ctx->nb_streams;i++) {
av_free(ctx->streams[i]->priv_data);
}
- av_free(s);
return -ENOMEM;
}
@@ -409,9 +402,37 @@ static int mpeg_mux_end(AVFormatContext *ctx)
#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 */
+ for(i=0;i<p->buf_size;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 - 1;
+ else
+ return 0;
+ }
+ }
+ return 0;
+}
+
+
typedef struct MpegDemuxContext {
int header_state;
- int mux_rate; /* 50 byte/s unit */
} MpegDemuxContext;
static int find_start_code(ByteIOContext *pb, int *size_ptr,
@@ -441,188 +462,12 @@ static int find_start_code(ByteIOContext *pb, int *size_ptr,
return val;
}
-static int check_stream_id(AVFormatContext *s, int c_id)
-{
- AVStream *st;
- int i;
-
- for(i = 0;i < s->nb_streams;i++) {
- st = s->streams[i];
- if (st && st->id == c_id)
- return 1;
- }
- return 0;
-}
-
-static int mpeg_mux_read_header(AVFormatContext *s,
- AVFormatParameters *ap)
+static int mpegps_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
{
- MpegDemuxContext *m;
- int size, startcode, c, rate_bound, audio_bound, video_bound, mux_rate, val;
- int codec_id, n, i, type, seems_dvd;
- AVStream *st;
- offset_t start_pos;
-
- m = av_mallocz(sizeof(MpegDemuxContext));
- if (!m)
- return -ENOMEM;
- s->priv_data = m;
- seems_dvd = 0;
-
- /* search first pack header */
+ MpegDemuxContext *m = s->priv_data;
m->header_state = 0xff;
- size = MAX_SYNC_SIZE;
- start_pos = url_ftell(&s->pb); /* remember this pos */
- for(;;) {
- /*while (size > 0) {
- startcode = find_start_code(&s->pb, &size, &m->header_state);
- if (startcode == PACK_START_CODE)
- goto found;
- }*/
- /* System Header not found find streams searching through file */
- //fprintf(stderr,"libav: MPEG-PS System Header not found!\n");
- url_fseek(&s->pb, start_pos, SEEK_SET);
- video_bound = 0;
- audio_bound = 0;
- c = 0;
- s->nb_streams = 0;
- //size = 15*MAX_SYNC_SIZE;
- while (size > 0) {
- type = 0;
- codec_id = 0;
- n = 0;
- startcode = find_start_code(&s->pb, &size, &m->header_state);
- //fprintf(stderr,"\nstartcode: %x pos=0x%Lx\n", startcode, url_ftell(&s->pb));
- if (startcode == 0x1bd) {
- url_fseek(&s->pb, -4, SEEK_CUR);
- size += 4;
- startcode = mpeg_mux_check_packet(s, &size);
- //fprintf(stderr,"\nstartcode: %x pos=0x%Lx\n", startcode, url_ftell(&s->pb));
- if (startcode >= 0x80 && startcode <= 0x9f && !check_stream_id(s, startcode)) {
- //fprintf(stderr,"Found AC3 stream ID: 0x%x\n", startcode);
- type = CODEC_TYPE_AUDIO;
- codec_id = CODEC_ID_AC3;
- audio_bound++;
- n = 1;
- c = startcode;
- seems_dvd = 1;
- }
- } else if (startcode == 0x1e0 && !check_stream_id(s, startcode)) {
- //fprintf(stderr,"Found MPEGVIDEO stream ID: 0x%x\n", startcode);
- type = CODEC_TYPE_VIDEO;
- codec_id = CODEC_ID_MPEG1VIDEO;
- n = 1;
- c = startcode;
- video_bound++;
- } else if (startcode >= 0x1c0 && startcode <= 0x1df && !seems_dvd && !check_stream_id(s, startcode)) {
- //fprintf(stderr,"Found MPEGAUDIO stream ID: 0x%x\n", startcode);
- type = CODEC_TYPE_AUDIO;
- codec_id = CODEC_ID_MP2;
- n = 1;
- c = startcode;
- audio_bound++;
- }
- for(i=0;i<n;i++) {
- st = av_mallocz(sizeof(AVStream));
- if (!st)
- return -ENOMEM;
- s->streams[s->nb_streams++] = st;
- st->id = c;
- st->codec.codec_type = type;
- st->codec.codec_id = codec_id;
- }
- }
- if (video_bound || audio_bound) {
- url_fseek(&s->pb, start_pos, SEEK_SET);
- return 0;
- } else
- return -ENODATA;
- found:
- /* search system header just after pack header */
- /* parse pack header */
- get_byte(&s->pb); /* ts1 */
- get_be16(&s->pb); /* ts2 */
- get_be16(&s->pb); /* ts3 */
-
- mux_rate = get_byte(&s->pb) << 16;
- mux_rate |= get_byte(&s->pb) << 8;
- mux_rate |= get_byte(&s->pb);
- mux_rate &= (1 << 22) - 1;
- m->mux_rate = mux_rate;
-
- startcode = find_start_code(&s->pb, &size, &m->header_state);
- if (startcode == SYSTEM_HEADER_START_CODE)
- break;
- }
- size = get_be16(&s->pb);
- rate_bound = get_byte(&s->pb) << 16;
- rate_bound |= get_byte(&s->pb) << 8;
- rate_bound |= get_byte(&s->pb);
- rate_bound = (rate_bound >> 1) & ((1 << 22) - 1);
- audio_bound = get_byte(&s->pb) >> 2;
- video_bound = get_byte(&s->pb) & 0x1f;
- get_byte(&s->pb); /* reserved byte */
-#if 0
- printf("mux_rate=%d kbit/s\n", (m->mux_rate * 50 * 8) / 1000);
- printf("rate_bound=%d\n", rate_bound);
- printf("audio_bound=%d\n", audio_bound);
- printf("video_bound=%d\n", video_bound);
-#endif
- size -= 6;
- s->nb_streams = 0;
- while (size > 0) {
- c = get_byte(&s->pb);
- size--;
- if ((c & 0x80) == 0)
- break;
- val = get_be16(&s->pb);
- size -= 2;
- if (c >= 0xc0 && c <= 0xdf) {
- /* mpeg audio stream */
- type = CODEC_TYPE_AUDIO;
- codec_id = CODEC_ID_MP2;
- n = 1;
- c = c | 0x100;
- } else if (c >= 0xe0 && c <= 0xef) {
- type = CODEC_TYPE_VIDEO;
- codec_id = CODEC_ID_MPEG1VIDEO;
- n = 1;
- c = c | 0x100;
- } else if (c == 0xb8) {
- /* all audio streams */
- /* XXX: hack for DVD: we force AC3, although we do not
- know that this codec will be used */
- type = CODEC_TYPE_AUDIO;
- codec_id = CODEC_ID_AC3;
- /* XXX: Another hack for DVD: it seems, that AC3 streams
- aren't signaled on audio_bound on some DVDs (Matrix) */
- if (audio_bound == 0)
- audio_bound++;
- n = audio_bound;
- c = 0x80;
- //c = 0x1c0;
- } else if (c == 0xb9) {
- /* all video streams */
- type = CODEC_TYPE_VIDEO;
- codec_id = CODEC_ID_MPEG1VIDEO;
- n = video_bound;
- c = 0x1e0;
- } else {
- type = 0;
- codec_id = 0;
- n = 0;
- }
- for(i=0;i<n;i++) {
- st = av_mallocz(sizeof(AVStream));
- if (!st)
- return -ENOMEM;
- s->streams[s->nb_streams++] = st;
- st->id = c + i;
- st->codec.codec_type = type;
- st->codec.codec_id = codec_id;
- }
- }
-
+ /* no need to do more */
return 0;
}
@@ -641,12 +486,12 @@ static INT64 get_pts(ByteIOContext *pb, int c)
return pts;
}
-static int mpeg_mux_read_packet(AVFormatContext *s,
- AVPacket *pkt)
+static int mpegps_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
{
MpegDemuxContext *m = s->priv_data;
AVStream *st;
- int len, size, startcode, i, c, flags, header_len;
+ int len, size, startcode, i, c, flags, header_len, type, codec_id;
INT64 pts, dts;
/* next start code (should be immediately after */
@@ -745,149 +590,69 @@ static int mpeg_mux_read_packet(AVFormatContext *s,
if (st->id == startcode)
goto found;
}
- /* skip packet */
- url_fskip(&s->pb, len);
- goto redo;
+ /* no stream found: add a new stream */
+ st = av_new_stream(s, startcode);
+ if (!st)
+ goto skip;
+ if (startcode >= 0x1e0 && startcode <= 0x1ef) {
+ type = CODEC_TYPE_VIDEO;
+ codec_id = CODEC_ID_MPEG1VIDEO;
+ } 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;
+ codec_id = CODEC_ID_AC3;
+ } else {
+ skip:
+ /* skip packet */
+ url_fskip(&s->pb, len);
+ goto redo;
+ }
+ st->codec.codec_type = type;
+ st->codec.codec_id = codec_id;
found:
av_new_packet(pkt, len);
//printf("\nRead Packet ID: %x PTS: %f Size: %d", startcode,
// (float)pts/90000, len);
get_buffer(&s->pb, pkt->data, pkt->size);
pkt->pts = pts;
- pkt->stream_index = i;
+ pkt->stream_index = st->index;
return 0;
}
-static int mpeg_mux_check_packet(AVFormatContext *s, int *size)
-{
- MpegDemuxContext *m = s->priv_data;
- int len, startcode, c, n, flags, header_len;
- INT64 pts, dts;
-
- /* next start code (should be immediately after */
- redo:
- m->header_state = 0xff;
- startcode = find_start_code(&s->pb, size, &m->header_state);
-
- 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);
- goto redo;
- }
- /* find matching stream */
- if (!((startcode >= 0x1c0 && startcode <= 0x1df) ||
- (startcode >= 0x1e0 && startcode <= 0x1ef) ||
- (startcode == 0x1bd)))
- goto redo;
-
- n = *size;
- len = get_be16(&s->pb);
- n -= 2;
- pts = 0;
- dts = 0;
- /* stuffing */
- for(;;) {
- c = get_byte(&s->pb);
- len--;
- n--;
- /* XXX: for mpeg1, should test only bit 7 */
- if (c != 0xff)
- break;
- }
- if ((c & 0xc0) == 0x40) {
- /* buffer scale & size */
- get_byte(&s->pb);
- c = get_byte(&s->pb);
- len -= 2;
- n -= 2;
- }
- if ((c & 0xf0) == 0x20) {
- pts = get_pts(&s->pb, c);
- len -= 4;
- n -= 4;
- dts = pts;
- } else if ((c & 0xf0) == 0x30) {
- pts = get_pts(&s->pb, c);
- dts = get_pts(&s->pb, -1);
- len -= 9;
- n -= 9;
- } else if ((c & 0xc0) == 0x80) {
- /* mpeg 2 PES */
- if ((c & 0x30) != 0) {
- fprintf(stderr, "Encrypted multiplex not handled\n");
- return -EIO;
- }
- flags = get_byte(&s->pb);
- header_len = get_byte(&s->pb);
- len -= 2;
- n -= 2;
- if (header_len > len)
- goto redo;
- if ((flags & 0xc0) == 0x40) {
- pts = get_pts(&s->pb, -1);
- dts = pts;
- header_len -= 5;
- len -= 5;
- n -= 5;
- } if ((flags & 0xc0) == 0xc0) {
- pts = get_pts(&s->pb, -1);
- dts = get_pts(&s->pb, -1);
- header_len -= 10;
- len -= 10;
- n -= 10;
- }
- len -= header_len;
- n -= header_len;
- while (header_len > 0) {
- get_byte(&s->pb);
- header_len--;
- }
- }
- if (startcode == 0x1bd) {
- startcode = get_byte(&s->pb);
- len--;
- n--;
- if (startcode >= 0x80 && startcode <= 0xbf) {
- /* audio: skip header */
- get_byte(&s->pb);
- get_byte(&s->pb);
- get_byte(&s->pb);
- len -= 3;
- n -= 3;
- }
- }
- *size = n;
- return startcode;
-}
-
-
-static int mpeg_mux_read_close(AVFormatContext *s)
+static int mpegps_read_close(AVFormatContext *s)
{
- MpegDemuxContext *m = s->priv_data;
- av_free(m);
return 0;
}
-AVFormat mpeg_mux_format = {
+static AVOutputFormat mpegps_mux = {
"mpeg",
- "MPEG multiplex format",
+ "MPEG PS format",
"video/x-mpeg",
"mpg,mpeg,vob",
+ sizeof(MpegMuxContext),
CODEC_ID_MP2,
CODEC_ID_MPEG1VIDEO,
mpeg_mux_init,
mpeg_mux_write_packet,
mpeg_mux_end,
+};
- mpeg_mux_read_header,
- mpeg_mux_read_packet,
- mpeg_mux_read_close,
+static AVInputFormat mpegps_demux = {
+ "mpeg",
+ "MPEG PS format",
+ sizeof(MpegDemuxContext),
+ mpegps_probe,
+ mpegps_read_header,
+ mpegps_read_packet,
+ mpegps_read_close,
+ flags: AVFMT_NOHEADER,
};
+
+int mpegps_init(void)
+{
+ av_register_output_format(&mpegps_mux);
+ av_register_input_format(&mpegps_demux);
+ return 0;
+}