diff options
author | Fabrice Bellard <fabrice@bellard.org> | 2003-08-11 16:16:49 +0000 |
---|---|---|
committer | Fabrice Bellard <fabrice@bellard.org> | 2003-08-11 16:16:49 +0000 |
commit | c95108037fa64fb80b306bc5bec12aa4c98208d1 (patch) | |
tree | ecd151dbe2763da5e99ab3e38d12662c078073bf /libavformat | |
parent | 62563c38d0aaa8905b46280104f8211b91a38e43 (diff) | |
download | ffmpeg-c95108037fa64fb80b306bc5bec12aa4c98208d1.tar.gz |
support for older real audio files (<= version 3)
Originally committed as revision 2119 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/rm.c | 253 |
1 files changed, 166 insertions, 87 deletions
diff --git a/libavformat/rm.c b/libavformat/rm.c index c4be2e37a3..e99ae8c870 100644 --- a/libavformat/rm.c +++ b/libavformat/rm.c @@ -39,6 +39,7 @@ typedef struct { StreamInfo *audio_stream, *video_stream; int data_pos; /* position of the data after the header */ int nb_packets; + int old_format; } RMContext; static void put_str(ByteIOContext *s, const char *tag) @@ -465,6 +466,85 @@ static void get_str8(ByteIOContext *pb, char *buf, int buf_size) *q = '\0'; } +static void rm_read_audio_stream_info(AVFormatContext *s, AVStream *st, + int read_all) +{ + ByteIOContext *pb = &s->pb; + char buf[128]; + uint32_t version; + int i; + + /* ra type header */ + version = get_be32(pb); /* version */ + if (((version >> 16) & 0xff) == 3) { + /* very old version */ + for(i = 0; i < 14; i++) + get_byte(pb); + get_str8(pb, s->title, sizeof(s->title)); + get_str8(pb, s->author, sizeof(s->author)); + get_str8(pb, s->copyright, sizeof(s->copyright)); + get_str8(pb, s->comment, sizeof(s->comment)); + get_byte(pb); + get_str8(pb, buf, sizeof(buf)); + st->codec.sample_rate = 8000; + st->codec.channels = 1; + st->codec.codec_type = CODEC_TYPE_AUDIO; + st->codec.codec_id = CODEC_ID_RA_144; + } else { + /* old version (4) */ + get_be32(pb); /* .ra4 */ + get_be32(pb); + get_be16(pb); + get_be32(pb); /* header size */ + get_be16(pb); /* add codec info */ + get_be32(pb); /* coded frame size */ + get_be32(pb); /* ??? */ + get_be32(pb); /* ??? */ + get_be32(pb); /* ??? */ + get_be16(pb); /* 1 */ + get_be16(pb); /* coded frame size */ + get_be32(pb); + st->codec.sample_rate = get_be16(pb); + get_be32(pb); + st->codec.channels = get_be16(pb); + get_str8(pb, buf, sizeof(buf)); /* desc */ + get_str8(pb, buf, sizeof(buf)); /* desc */ + st->codec.codec_type = CODEC_TYPE_AUDIO; + if (!strcmp(buf, "dnet")) { + st->codec.codec_id = CODEC_ID_AC3; + } else { + st->codec.codec_id = CODEC_ID_NONE; + pstrcpy(st->codec.codec_name, sizeof(st->codec.codec_name), + buf); + } + if (read_all) { + get_byte(pb); + get_byte(pb); + get_byte(pb); + + get_str8(pb, s->title, sizeof(s->title)); + get_str8(pb, s->author, sizeof(s->author)); + get_str8(pb, s->copyright, sizeof(s->copyright)); + get_str8(pb, s->comment, sizeof(s->comment)); + } + } +} + +static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap) +{ + RMContext *rm = s->priv_data; + AVStream *st; + + rm->old_format = 1; + st = av_new_stream(s, 0); + if (!st) + goto fail; + rm_read_audio_stream_info(s, st, 1); + return 0; + fail: + return -1; +} + static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) { RMContext *rm = s->priv_data; @@ -477,8 +557,13 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) char buf[128]; int flags = 0; - if (get_le32(pb) != MKTAG('.', 'R', 'M', 'F')) + tag = get_le32(pb); + if (tag == MKTAG('.', 'r', 'a', 0xfd)) { + /* very old .ra format */ + return rm_read_header_old(s, ap); + } else if (tag != MKTAG('.', 'R', 'M', 'F')) { return -EIO; + } get_be32(pb); /* header size */ get_be16(pb); @@ -545,32 +630,7 @@ static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) v = get_be32(pb); if (v == MKTAG(0xfd, 'a', 'r', '.')) { /* ra type header */ - get_be32(pb); /* version */ - get_be32(pb); /* .ra4 */ - get_be32(pb); - get_be16(pb); - get_be32(pb); /* header size */ - get_be16(pb); /* add codec info */ - get_be32(pb); /* coded frame size */ - get_be32(pb); /* ??? */ - get_be32(pb); /* ??? */ - get_be32(pb); /* ??? */ - get_be16(pb); /* 1 */ - get_be16(pb); /* coded frame size */ - get_be32(pb); - st->codec.sample_rate = get_be16(pb); - get_be32(pb); - st->codec.channels = get_be16(pb); - get_str8(pb, buf, sizeof(buf)); /* desc */ - get_str8(pb, buf, sizeof(buf)); /* desc */ - st->codec.codec_type = CODEC_TYPE_AUDIO; - if (!strcmp(buf, "dnet")) { - st->codec.codec_id = CODEC_ID_AC3; - } else { - st->codec.codec_id = CODEC_ID_NONE; - pstrcpy(st->codec.codec_name, sizeof(st->codec.codec_name), - buf); - } + rm_read_audio_stream_info(s, st, 0); } else { if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) { fail1: @@ -645,6 +705,9 @@ static int get_num(ByteIOContext *pb, int *len) } } +/* multiple of 20 bytes for ra144 (ugly) */ +#define RAW_PACKET_SIZE 1000 + static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) { RMContext *rm = s->priv_data; @@ -654,66 +717,80 @@ static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) uint8_t *ptr; int flags; - redo: - if (rm->nb_packets == 0) - return -EIO; - get_be16(pb); - len = get_be16(pb); - if (len < 12) - return -EIO; - num = get_be16(pb); - timestamp = get_be32(pb); - get_byte(pb); /* reserved */ - flags = get_byte(pb); /* flags */ - rm->nb_packets--; - len -= 12; - - st = NULL; - for(i=0;i<s->nb_streams;i++) { - st = s->streams[i]; - if (num == st->id) - break; - } - if (i == s->nb_streams) { - /* skip packet if unknown number */ - url_fskip(pb, len); - goto redo; - } - - if (st->codec.codec_type == CODEC_TYPE_VIDEO) { - int full_frame, h, pic_num; - - h= get_byte(pb); - if ((h & 0xc0) == 0xc0) { - int len2, pos; - full_frame = 1; - len2= get_num(pb, &len); - pos = get_num(pb, &len); - //printf("pos:%d\n",len); - len -= 2; - } else { - int seq, frame_size, pos; - full_frame = 0; - seq = get_byte(pb); - frame_size = get_num(pb, &len); - pos = get_num(pb, &len); - //printf("seq:%d, size:%d, pos:%d\n",seq,frame_size,pos); - len -= 3; + if (rm->old_format) { + /* just read raw bytes */ + len = RAW_PACKET_SIZE; + av_new_packet(pkt, len); + pkt->stream_index = 0; + len = get_buffer(pb, pkt->data, len); + if (len <= 0) { + av_free_packet(pkt); + return -EIO; } - /* picture number */ - pic_num= get_byte(pb); - - //XXX/FIXME/HACK, demuxer should be fixed to send complete frames ... - if(st->codec.slice_offset==NULL) - st->codec.slice_offset= (int*)av_malloc(sizeof(int)); - st->codec.slice_count= full_frame; - st->codec.slice_offset[0]= 0; + pkt->size = len; + st = s->streams[0]; + } else { + redo: + if (rm->nb_packets == 0) + return -EIO; + get_be16(pb); + len = get_be16(pb); + if (len < 12) + return -EIO; + num = get_be16(pb); + timestamp = get_be32(pb); + get_byte(pb); /* reserved */ + flags = get_byte(pb); /* flags */ + rm->nb_packets--; + len -= 12; + + st = NULL; + for(i=0;i<s->nb_streams;i++) { + st = s->streams[i]; + if (num == st->id) + break; + } + if (i == s->nb_streams) { + /* skip packet if unknown number */ + url_fskip(pb, len); + goto redo; + } + + if (st->codec.codec_type == CODEC_TYPE_VIDEO) { + int full_frame, h, pic_num; + + h= get_byte(pb); + if ((h & 0xc0) == 0xc0) { + int len2, pos; + full_frame = 1; + len2= get_num(pb, &len); + pos = get_num(pb, &len); + //printf("pos:%d\n",len); + len -= 2; + } else { + int seq, frame_size, pos; + full_frame = 0; + seq = get_byte(pb); + frame_size = get_num(pb, &len); + pos = get_num(pb, &len); + //printf("seq:%d, size:%d, pos:%d\n",seq,frame_size,pos); + len -= 3; + } + /* picture number */ + pic_num= get_byte(pb); + + //XXX/FIXME/HACK, demuxer should be fixed to send complete frames ... + if(st->codec.slice_offset==NULL) + st->codec.slice_offset= (int*)av_malloc(sizeof(int)); + st->codec.slice_count= full_frame; + st->codec.slice_offset[0]= 0; + } + + av_new_packet(pkt, len); + pkt->stream_index = i; + get_buffer(pb, pkt->data, len); } - av_new_packet(pkt, len); - pkt->stream_index = i; - get_buffer(pb, pkt->data, len); - /* for AC3, needs to swap bytes */ if (st->codec.codec_id == CODEC_ID_AC3) { ptr = pkt->data; @@ -737,9 +814,11 @@ static int rm_probe(AVProbeData *p) /* check file header */ if (p->buf_size <= 32) return 0; - if (p->buf[0] == '.' && p->buf[1] == 'R' && - p->buf[2] == 'M' && p->buf[3] == 'F' && - p->buf[4] == 0 && p->buf[5] == 0) + if ((p->buf[0] == '.' && p->buf[1] == 'R' && + p->buf[2] == 'M' && p->buf[3] == 'F' && + p->buf[4] == 0 && p->buf[5] == 0) || + (p->buf[0] == '.' && p->buf[1] == 'r' && + p->buf[2] == 'a' && p->buf[3] == 0xfd)) return AVPROBE_SCORE_MAX; else return 0; |