-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 {
- int flavor, sub_packet_h, coded_framesize;
- /* old version (4) */
- get_be32(pb); /* .ra4 */
- get_be32(pb); /* data size */
- get_be16(pb); /* version2 */
- get_be32(pb); /* header size */
- flavor= get_be16(pb); /* add codec info / flavor */
- coded_framesize= get_be32(pb); /* coded frame size */
- get_be32(pb); /* ??? */
- get_be32(pb); /* ??? */
- get_be32(pb); /* ??? */
- sub_packet_h= get_be16(pb); /* 1 */
- get_be16(pb); /* frame size */
- get_be16(pb); /* sub packet size */
- get_be16(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 if (!strcmp(buf, "28_8")) {
- st->codec.codec_id = CODEC_ID_RA_288;
- st->codec.extradata_size= 10;
- st->codec.extradata= av_mallocz(st->codec.extradata_size);
- /* this is completly braindead and broken, the idiot who added this codec and endianness
- specific reordering to mplayer and libavcodec/ra288.c should be drowned in a see of cola */
- //FIXME pass the unpermutated extradata
- ((uint16_t*)st->codec.extradata)[1]= sub_packet_h;
- ((uint16_t*)st->codec.extradata)[2]= flavor;
- ((uint16_t*)st->codec.extradata)[3]= coded_framesize;
- } 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;
- AVStream *st;
- ByteIOContext *pb = &s->pb;
- unsigned int tag, v;
- int tag_size, size, codec_data_size, i;
- int64_t codec_pos;
- unsigned int h263_hack_version, start_time, duration;
- char buf[128];
- int flags = 0;
-
- 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 AVERROR_IO;
- }
-
- get_be32(pb); /* header size */
- get_be16(pb);
- get_be32(pb);
- get_be32(pb); /* number of headers */
-
- for(;;) {
- if (url_feof(pb))
- goto fail;
- tag = get_le32(pb);
- tag_size = get_be32(pb);
- get_be16(pb);
-#if 0
- printf("tag=%c%c%c%c (%08x) size=%d\n",
- (tag) & 0xff,
- (tag >> 8) & 0xff,
- (tag >> 16) & 0xff,
- (tag >> 24) & 0xff,
- tag,
- tag_size);
-#endif
- if (tag_size < 10)
- goto fail;
- switch(tag) {
- case MKTAG('P', 'R', 'O', 'P'):
- /* file header */
- get_be32(pb); /* max bit rate */
- get_be32(pb); /* avg bit rate */
- get_be32(pb); /* max packet size */
- get_be32(pb); /* avg packet size */
- get_be32(pb); /* nb packets */
- get_be32(pb); /* duration */
- get_be32(pb); /* preroll */
- get_be32(pb); /* index offset */
- get_be32(pb); /* data offset */
- get_be16(pb); /* nb streams */
- flags = get_be16(pb); /* flags */
- break;
- case MKTAG('C', 'O', 'N', 'T'):
- get_str(pb, s->title, sizeof(s->title));
- get_str(pb, s->author, sizeof(s->author));
- get_str(pb, s->copyright, sizeof(s->copyright));
- get_str(pb, s->comment, sizeof(s->comment));
- break;
- case MKTAG('M', 'D', 'P', 'R'):
- st = av_new_stream(s, 0);
- if (!st)
- goto fail;
- st->id = get_be16(pb);
- get_be32(pb); /* max bit rate */
- st->codec.bit_rate = get_be32(pb); /* bit rate */
- get_be32(pb); /* max packet size */
- get_be32(pb); /* avg packet size */
- start_time = get_be32(pb); /* start time */
- get_be32(pb); /* preroll */
- duration = get_be32(pb); /* duration */
- st->start_time = start_time * (AV_TIME_BASE / 1000);
- st->duration = duration * (AV_TIME_BASE / 1000);
- get_str8(pb, buf, sizeof(buf)); /* desc */
- get_str8(pb, buf, sizeof(buf)); /* mimetype */
- codec_data_size = get_be32(pb);
- codec_pos = url_ftell(pb);
- st->codec.codec_type = CODEC_TYPE_DATA;
- av_set_pts_info(st, 64, 1, 1000);
-
- v = get_be32(pb);
- if (v == MKTAG(0xfd, 'a', 'r', '.')) {
- /* ra type header */
- rm_read_audio_stream_info(s, st, 0);
- } else {
- int fps, fps2;
- if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) {
- fail1:
- av_log(&st->codec, AV_LOG_ERROR, "Unsupported video codec\n");
- goto skip;
- }
- st->codec.codec_tag = get_le32(pb);
-// av_log(NULL, AV_LOG_DEBUG, "%X %X\n", st->codec.codec_tag, MKTAG('R', 'V', '2', '0'));
- if ( st->codec.codec_tag != MKTAG('R', 'V', '1', '0')
- && st->codec.codec_tag != MKTAG('R', 'V', '2', '0')
- && st->codec.codec_tag != MKTAG('R', 'V', '3', '0')
- && st->codec.codec_tag != MKTAG('R', 'V', '4', '0'))
- goto fail1;
- st->codec.width = get_be16(pb);
- st->codec.height = get_be16(pb);
- st->codec.frame_rate_base= 1;
- fps= get_be16(pb);
- st->codec.codec_type = CODEC_TYPE_VIDEO;
- get_be32(pb);
- fps2= get_be16(pb);
- get_be16(pb);
-
- st->codec.extradata_size= codec_data_size - (url_ftell(pb) - codec_pos);
- st->codec.extradata= av_malloc(st->codec.extradata_size);
- get_buffer(pb, st->codec.extradata, st->codec.extradata_size);
-
-// av_log(NULL, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
- st->codec.frame_rate = fps * st->codec.frame_rate_base;
- /* modification of h263 codec version (!) */
-#ifdef WORDS_BIGENDIAN
- h263_hack_version = ((uint32_t*)st->codec.extradata)[1];
-#else
- h263_hack_version = bswap_32(((uint32_t*)st->codec.extradata)[1]);
-#endif
- st->codec.sub_id = h263_hack_version;
- switch((h263_hack_version>>28)){
- case 1: st->codec.codec_id = CODEC_ID_RV10; break;
- case 2: st->codec.codec_id = CODEC_ID_RV20; break;
- case 3: st->codec.codec_id = CODEC_ID_RV30; break;
- case 4: st->codec.codec_id = CODEC_ID_RV40; break;
- default: goto fail1;
- }
- }
-skip:
- /* skip codec info */
- size = url_ftell(pb) - codec_pos;
- url_fskip(pb, codec_data_size - size);
- break;
- case MKTAG('D', 'A', 'T', 'A'):
- goto header_end;
- default:
- /* unknown tag: skip it */
- url_fskip(pb, tag_size - 10);
- break;
- }
- }
- header_end:
- rm->nb_packets = get_be32(pb); /* number of packets */
- if (!rm->nb_packets && (flags & 4))
- rm->nb_packets = 3600 * 25;
- get_be32(pb); /* next data header */
- return 0;
-
- fail:
- for(i=0;i<s->nb_streams;i++) {
- av_free(s->streams[i]);
- }
- return AVERROR_IO;
-}
-
-static int get_num(ByteIOContext *pb, int *len)
-{
- int n, n1;
-
- n = get_be16(pb);
- (*len)-=2;
- if (n >= 0x4000) {
- return n - 0x4000;
- } else {
- n1 = get_be16(pb);
- (*len)-=2;
- return (n << 16) | n1;
- }
-}
-
-/* multiple of 20 bytes for ra144 (ugly) */
-#define RAW_PACKET_SIZE 1000
-
-static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
- RMContext *rm = s->priv_data;
- ByteIOContext *pb = &s->pb;
- int len, num, res, i;
- AVStream *st;
- uint32_t state=0xFFFFFFFF;
-
- while(!url_feof(pb)){
- *pos= url_ftell(pb);
- if(rm->remaining_len > 0){
- num= rm->current_stream;
- len= rm->remaining_len;
- *timestamp = AV_NOPTS_VALUE;
- *flags= 0;
- }else{
- state= (state<<8) + get_byte(pb);
-
- if(state == MKBETAG('I', 'N', 'D', 'X')){
- len = get_be16(pb) - 6;
- if(len<0)
- continue;
- goto skip;
- }
-
- if(state > (unsigned)0xFFFF || state < 12)
- continue;
- len=state;
- state= 0xFFFFFFFF;
-
- num = get_be16(pb);
- *timestamp = get_be32(pb);
- res= get_byte(pb); /* reserved */
- *flags = get_byte(pb); /* flags */
-
-
- len -= 12;
- }
- for(i=0;i<s->nb_streams;i++) {
- st = s->streams[i];
- if (num == st->id)
- break;
- }
- if (i == s->nb_streams) {
-skip:
- /* skip packet if unknown number */
- url_fskip(pb, len);
- rm->remaining_len -= len;
- continue;
- }
- *stream_index= i;
-
- return len;
- }
- return -1;
-}
-
-static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
-{
- RMContext *rm = s->priv_data;
- ByteIOContext *pb = &s->pb;
- AVStream *st;
- int i, len, tmp, j;
- int64_t timestamp, pos;
- uint8_t *ptr;
- int flags;
-
- 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 AVERROR_IO;
- }
- pkt->size = len;
- st = s->streams[0];
- } else {
- int seq=1;
-resync:
- len=sync(s, ×tamp, &flags, &i, &pos);
- if(len<0)
- return AVERROR_IO;
- st = s->streams[i];
-
- if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
- int h, pic_num, len2, pos;
-
- h= get_byte(pb); len--;
- if(!(h & 0x40)){
- seq = get_byte(pb); len--;
- }
-
- if((h & 0xc0) == 0x40){
- len2= pos= 0;
- }else{
- len2 = get_num(pb, &len);
- pos = get_num(pb, &len);
- }
- /* picture number */
- pic_num= get_byte(pb); len--;
- rm->remaining_len= len;
- rm->current_stream= st->id;
-
-// av_log(NULL, AV_LOG_DEBUG, "%X len:%d pos:%d len2:%d pic_num:%d\n",h, len, pos, len2, pic_num);
- if(len2 && len2<len)
- len=len2;
- rm->remaining_len-= len;
- }
-
- if(st->discard){
- url_fskip(pb, len);
- goto resync;
- }
-
- av_new_packet(pkt, len);
- pkt->stream_index = i;
- get_buffer(pb, pkt->data, len);
-
-#if 0
- if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
- if(st->codec.codec_id == CODEC_ID_RV20){
- int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1);
- av_log(NULL, AV_LOG_DEBUG, "%d %Ld %d\n", timestamp, timestamp*512LL/25, seq);
-
- seq |= (timestamp&~0x3FFF);
- if(seq - timestamp > 0x2000) seq -= 0x4000;
- if(seq - timestamp < -0x2000) seq += 0x4000;
- }
- }
-#endif
- pkt->pts= timestamp;
- if(flags&2){
- pkt->flags |= PKT_FLAG_KEY;
- if((seq&0x7F) == 1)
- av_add_index_entry(st, pos, timestamp, 0, AVINDEX_KEYFRAME);
- }
- }
-
- /* for AC3, needs to swap bytes */
- if (st->codec.codec_id == CODEC_ID_AC3) {
- ptr = pkt->data;
- for(j=0;j<len;j+=2) {
- tmp = ptr[0];
- ptr[0] = ptr[1];
- ptr[1] = tmp;
- ptr += 2;
- }
- }
- return 0;
-}
-
-static int rm_read_close(AVFormatContext *s)
-{
- return 0;
-}
-
-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) ||
- (p->buf[0] == '.' && p->buf[1] == 'r' &&
- p->buf[2] == 'a' && p->buf[3] == 0xfd))
- return AVPROBE_SCORE_MAX;
- else
- return 0;
-}
-
-static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
- int64_t *ppos, int64_t pos_limit)
-{
- RMContext *rm = s->priv_data;
- int64_t pos, dts;
- int stream_index2, flags, len, h;
-
- pos = *ppos;
-
- if(rm->old_format)
- return AV_NOPTS_VALUE;
-
- url_fseek(&s->pb, pos, SEEK_SET);
- rm->remaining_len=0;
- for(;;){
- int seq=1;
- AVStream *st;
-
- len=sync(s, &dts, &flags, &stream_index2, &pos);
- if(len<0)
- return AV_NOPTS_VALUE;
-
- st = s->streams[stream_index2];
- if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
- h= get_byte(&s->pb); len--;
- if(!(h & 0x40)){
- seq = get_byte(&s->pb); len--;
- }
- }
-
- if((flags&2) && (seq&0x7F) == 1){
-// av_log(s, AV_LOG_DEBUG, "%d %d-%d %Ld %d\n", flags, stream_index2, stream_index, dts, seq);
- av_add_index_entry(st, pos, dts, 0, AVINDEX_KEYFRAME);
- if(stream_index2 == stream_index)
- break;
- }
-
- url_fskip(&s->pb, len);
- }
- *ppos = pos;
- return dts;
-}
-
-static AVInputFormat rm_iformat = {
- "rm",
- "rm format",
- sizeof(RMContext),
- rm_probe,
- rm_read_header,
- rm_read_packet,
- rm_read_close,
- NULL,
- rm_read_dts,
-};
-
-#ifdef CONFIG_ENCODERS
-static AVOutputFormat rm_oformat = {
- "rm",
- "rm format",
- "application/vnd.rn-realmedia",
- "rm,ra",
- sizeof(RMContext),
- CODEC_ID_AC3,
- CODEC_ID_RV10,
- rm_write_header,
- rm_write_packet,
- rm_write_trailer,