aboutsummaryrefslogtreecommitdiffstats
path: root/libav/mpeg.c
diff options
context:
space:
mode:
authorJuanjo <pulento@users.sourceforge.net>2002-03-17 17:44:45 +0000
committerJuanjo <pulento@users.sourceforge.net>2002-03-17 17:44:45 +0000
commit001e3f555daf02c6c48c5f3268c96a1b777dc7d0 (patch)
tree30cb70faf90bd350d7879edcd06e52216f567da6 /libav/mpeg.c
parent9cdd6a24ad90ff087d4d8c93d1b77b238d6d9aa9 (diff)
downloadffmpeg-001e3f555daf02c6c48c5f3268c96a1b777dc7d0.tar.gz
- Fixes on MPEG demuxer to handle VOBs without System Header.
Originally committed as revision 335 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libav/mpeg.c')
-rw-r--r--libav/mpeg.c188
1 files changed, 186 insertions, 2 deletions
diff --git a/libav/mpeg.c b/libav/mpeg.c
index f112a773b0..5ac9c62b18 100644
--- a/libav/mpeg.c
+++ b/libav/mpeg.c
@@ -59,6 +59,8 @@ 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)
{
@@ -393,6 +395,19 @@ 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)
{
@@ -400,6 +415,7 @@ static int mpeg_mux_read_header(AVFormatContext *s,
int size, startcode, c, rate_bound, audio_bound, video_bound, mux_rate, val;
int codec_id, n, i, type;
AVStream *st;
+ offset_t start_pos;
m = av_mallocz(sizeof(MpegDemuxContext));
if (!m)
@@ -409,13 +425,70 @@ static int mpeg_mux_read_header(AVFormatContext *s,
/* search first pack header */
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;
}
- return -ENODATA;
+ /* 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;
+ }
+ } 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 && !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 */
@@ -533,7 +606,7 @@ static int mpeg_mux_read_packet(AVFormatContext *s,
m->header_state = 0xff;
size = MAX_SYNC_SIZE;
startcode = find_start_code(&s->pb, &size, &m->header_state);
- // printf("startcode=%x pos=0x%Lx\n", startcode, url_ftell(&s->pb));
+ //printf("startcode=%x pos=0x%Lx\n", startcode, url_ftell(&s->pb));
if (startcode < 0)
return -EIO;
if (startcode == PACK_START_CODE)
@@ -635,6 +708,117 @@ static int mpeg_mux_read_packet(AVFormatContext *s,
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)
{
MpegDemuxContext *m = s->priv_data;