📄 rm.c
字号:
{ RMContext *rm = s->priv_data; ByteIOContext *pb = &s->pb; StreamInfo *stream = rm->video_stream; int key_frame = !!(flags & PKT_FLAG_KEY); /* XXX: this is incorrect: should be a parameter */ /* Well, I spent some time finding the meaning of these bits. I am not sure I understood everything, but it works !! */#if 1 write_packet_header(s, stream, size + 7, key_frame); /* bit 7: '1' if final packet of a frame converted in several packets */ put_byte(pb, 0x81); /* bit 7: '1' if I frame. bits 6..0 : sequence number in current frame starting from 1 */ if (key_frame) { put_byte(pb, 0x81); } else { put_byte(pb, 0x01); } put_be16(pb, 0x4000 + (size)); /* total frame size */ put_be16(pb, 0x4000 + (size)); /* offset from the start or the end */#else /* full frame */ write_packet_header(s, size + 6); put_byte(pb, 0xc0); put_be16(pb, 0x4000 + size); /* total frame size */ put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */#endif put_byte(pb, stream->nb_frames & 0xff); put_buffer(pb, buf, size); put_flush_packet(pb); stream->nb_frames++; return 0;}static int rm_write_packet(AVFormatContext *s, AVPacket *pkt){ if (s->streams[pkt->stream_index]->codec->codec_type == CODEC_TYPE_AUDIO) return rm_write_audio(s, pkt->data, pkt->size, pkt->flags); else return rm_write_video(s, pkt->data, pkt->size, pkt->flags);}static int rm_write_trailer(AVFormatContext *s){ RMContext *rm = s->priv_data; int data_size, index_pos, i; ByteIOContext *pb = &s->pb; if (!url_is_streamed(&s->pb)) { /* end of file: finish to write header */ index_pos = url_fseek(pb, 0, SEEK_CUR); data_size = index_pos - rm->data_pos; /* index */ put_tag(pb, "INDX"); put_be32(pb, 10 + 10 * s->nb_streams); put_be16(pb, 0); for(i=0;i<s->nb_streams;i++) { put_be32(pb, 0); /* zero indices */ put_be16(pb, i); /* stream number */ put_be32(pb, 0); /* next index */ } /* undocumented end header */ put_be32(pb, 0); put_be32(pb, 0); url_fseek(pb, 0, SEEK_SET); for(i=0;i<s->nb_streams;i++) rm->streams[i].total_frames = rm->streams[i].nb_frames; rv10_write_header(s, data_size, index_pos); } else { /* undocumented end header */ put_be32(pb, 0); put_be32(pb, 0); } put_flush_packet(pb); return 0;}#endif //CONFIG_MUXERS/***************************************************/static void get_str(ByteIOContext *pb, char *buf, int buf_size){ int len, i; char *q; len = get_be16(pb); q = buf; for(i=0;i<len;i++) { if (i < buf_size - 1) *q++ = get_byte(pb); } *q = '\0';}static void get_str8(ByteIOContext *pb, char *buf, int buf_size){ int len, i; char *q; len = get_byte(pb); q = buf; for(i=0;i<len;i++) { if (i < buf_size - 1) *q++ = get_byte(pb); } *q = '\0';}static void rm_read_audio_stream_info(AVFormatContext *s, AVStream *st, int read_all){ RMContext *rm = s->priv_data; ByteIOContext *pb = &s->pb; char buf[256]; uint32_t version; int i; /* ra type header */ version = get_be32(pb); /* version */ if (((version >> 16) & 0xff) == 3) { int64_t startpos = url_ftell(pb); /* 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)); if ((startpos + (version & 0xffff)) >= url_ftell(pb) + 2) { // fourcc (should always be "lpcJ") get_byte(pb); get_str8(pb, buf, sizeof(buf)); } // Skip extra header crap (this should never happen) if ((startpos + (version & 0xffff)) > url_ftell(pb)) url_fskip(pb, (version & 0xffff) + startpos - url_ftell(pb)); 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, sub_packet_size; /* 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 */ rm->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */ get_be32(pb); /* ??? */ get_be32(pb); /* ??? */ get_be32(pb); /* ??? */ rm->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */ st->codec->block_align= get_be16(pb); /* frame size */ rm->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */ get_be16(pb); /* ??? */ if (((version >> 16) & 0xff) == 5) { get_be16(pb); get_be16(pb); get_be16(pb); } st->codec->sample_rate = get_be16(pb); get_be32(pb); st->codec->channels = get_be16(pb); if (((version >> 16) & 0xff) == 5) { get_be32(pb); buf[0] = get_byte(pb); buf[1] = get_byte(pb); buf[2] = get_byte(pb); buf[3] = get_byte(pb); buf[4] = 0; } else { 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= 0; rm->audio_framesize = st->codec->block_align; st->codec->block_align = coded_framesize; rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h); } else if (!strcmp(buf, "cook")) { int codecdata_length, i; get_be16(pb); get_byte(pb); if (((version >> 16) & 0xff) == 5) get_byte(pb); codecdata_length = get_be32(pb); st->codec->codec_id = CODEC_ID_COOK; st->codec->extradata_size= codecdata_length; st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); for(i = 0; i < codecdata_length; i++) ((uint8_t*)st->codec->extradata)[i] = get_byte(pb); rm->audio_framesize = st->codec->block_align; st->codec->block_align = rm->sub_packet_size; rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h); } 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 && tag != MKTAG('D', 'A', 'T', 'A')) 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; st->duration = duration; 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->time_base.num= 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_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_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->time_base.den = fps * st->codec->time_base.num; /* 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -