📄 rm.c
字号:
// 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_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->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; } }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 1000static 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; len= av_get_packet(pb, pkt, len); pkt->stream_index = 0; if (len <= 0) { 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 >= AVDISCARD_NONKEY && !(flags&2)) || st->discard >= AVDISCARD_ALL){ url_fskip(pb, len); goto resync; } av_get_packet(pb, pkt, len); pkt->stream_index = i;#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_MUXERSstatic 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,};#endif //CONFIG_MUXERSint rm_init(void){ av_register_input_format(&rm_iformat);#ifdef CONFIG_MUXERS av_register_output_format(&rm_oformat);#endif //CONFIG_MUXERS return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -