Ticket #364: rmdec.diff

File rmdec.diff, 13.8 KB (added by Roy, 15 years ago)

rm timestamp workaround patch for libavformat

  • libavformat/rmdec.c

    diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c
    index d952391..baff50d 100644
    a b typedef struct {  
    4848    int remaining_len;
    4949    int audio_stream_num; ///< Stream number for audio packets
    5050    int audio_pkt_cnt; ///< Output packet counter
     51
     52    int video_after_seek;
     53    int64_t kf_base;    ///< timestamp of the prev. video keyframe
     54    uint32_t kf_pts;    ///< timestamp of next video keyframe
    5155} RMDemuxContext;
    5256
    5357static const unsigned char sipr_swaps[38][2] = {
    static const unsigned char sipr_swaps[38][2] = {  
    6569
    6670const unsigned char ff_sipr_subpk_size[4] = { 29, 19, 37, 20 };
    6771
     72#define RM_SKIP_BITS(n) buffer<<=n
     73#define RM_SHOW_BITS(n) ((buffer)>>(32-(n)))
     74
     75static int rm_fix_timestamp(uint8_t *buf, uint32_t timestamp, uint32_t format,
     76    int64_t *kf_base, int *kf_pts, int *pts)
     77{
     78    uint8_t *s = buf + 1 + (*buf+1)*8;
     79    uint32_t buffer = (s[0]<<24) + (s[1]<<16) + (s[2]<<8) + s[3];
     80    uint32_t kf = timestamp;
     81    int pict_type;
     82    uint32_t orig_kf;
     83
     84    if(format == MKTAG('R','V','3','0') || format == MKTAG('R','V','4','0')){
     85        if(format == MKTAG('R','V','3','0')){
     86            RM_SKIP_BITS(3);
     87            pict_type = RM_SHOW_BITS(2);
     88            RM_SKIP_BITS(2 + 7);
     89        }else{
     90            RM_SKIP_BITS(1);
     91            pict_type = RM_SHOW_BITS(2);
     92            RM_SKIP_BITS(2 + 7 + 3);
     93        }
     94        orig_kf = kf = RM_SHOW_BITS(13);  //    kf= 2*SHOW_BITS(12);
     95        if(pict_type <= 1){
     96            // I frame, sync timestamps:
     97            *kf_base = (int64_t)timestamp-kf;
     98            av_log(NULL, AV_LOG_DEBUG,"\nTS: base=%08"PRIX64"\n",*kf_base);
     99            kf = timestamp;
     100        } else {
     101            // P/B frame, merge timestamps:
     102            int64_t tmp = (int64_t)timestamp - *kf_base;
     103            kf |= tmp&(~0x1fff);    // combine with packet timestamp
     104            if(kf<tmp-4096) kf += 8192; else // workaround wrap-around problems
     105            if(kf>tmp+4096) kf -= 8192;
     106            kf += *kf_base;
     107        }
     108        if(pict_type != 3){ // P || I  frame -> swap timestamps
     109            uint32_t tmp=kf;
     110            kf = *kf_pts;
     111            *kf_pts = tmp;
     112        }
     113        av_log(NULL, AV_LOG_DEBUG,"\nTS: %08X -> %08X (%04X) %d %02X %02X %02X %02X %5u\n",
     114            timestamp,kf,orig_kf,pict_type,s[0],s[1],s[2],s[3],pts?kf-(*pts):0);
     115    }
     116    if(pts)
     117         *pts = kf;
     118    return kf;
     119}
     120
     121static void process_video_timestamp(RMDemuxContext *rm, uint32_t codec_tag,AVPacket *pkt)
     122{
     123    //FIXME: it seems that only RV30 can deliver the braindamaged AV_NOPTS_VALUE
     124    if(pkt->pts == AV_NOPTS_VALUE)
     125        return;
     126    if(rm->video_after_seek){
     127        rm->kf_base = 0;
     128        rm->kf_pts = pkt->pts;
     129        rm->video_after_seek = 0;
     130    }
     131    pkt->pts = rm_fix_timestamp(pkt->data, pkt->pts,
     132                                     codec_tag,
     133                                     &rm->kf_base, &rm->kf_pts,
     134                                     NULL);
     135}
     136
    68137static inline void get_strl(AVIOContext *pb, char *buf, int buf_size, int len)
    69138{
    70139    int i;
    71     char *q, r;
     140    char *q = buf, r;
    72141
    73142    q = buf;
    74143    for(i=0;i<len;i++) {
    static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,  
    125194                                     AVStream *st, RMStream *ast, int read_all)
    126195{
    127196    char buf[256];
    128     uint32_t version;
     197    uint32_t version,headsize;
    129198    int ret;
    130199
    131200    /* ra type header */
    132201    version = avio_rb16(pb); /* version */
     202    headsize = avio_rb16(pb);
    133203    if (version == 3) {
    134         int header_size = avio_rb16(pb);
    135204        int64_t startpos = avio_tell(pb);
     205        int64_t headoffset = startpos + headsize;
     206
    136207        avio_skip(pb, 14);
    137208        rm_read_metadata(s, 0);
    138         if ((startpos + header_size) >= avio_tell(pb) + 2) {
     209        if (headoffset >= avio_tell(pb) + 2) {
    139210            // fourcc (should always be "lpcJ")
    140211            avio_r8(pb);
    141212            get_str8(pb, buf, sizeof(buf));
    142213        }
    143214        // Skip extra header crap (this should never happen)
    144         if ((startpos + header_size) > avio_tell(pb))
    145             avio_skip(pb, header_size + startpos - avio_tell(pb));
     215        if (headoffset > avio_tell(pb))
     216            avio_skip(pb, headoffset - avio_tell(pb));
    146217        st->codec->sample_rate = 8000;
    147218        st->codec->channels = 1;
    148219        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
    149220        st->codec->codec_id = CODEC_ID_RA_144;
    150221    } else {
    151         int flavor, sub_packet_h, coded_framesize, sub_packet_size;
     222        int flavor;
    152223        int codecdata_length;
    153224        /* old version (4) */
    154         avio_skip(pb, 2); /* unused */
    155225        avio_rb32(pb); /* .ra4 */
    156226        avio_rb32(pb); /* data size */
    157227        avio_rb16(pb); /* version2 */
    158228        avio_rb32(pb); /* header size */
    159229        flavor= avio_rb16(pb); /* add codec info / flavor */
    160         ast->coded_framesize = coded_framesize = avio_rb32(pb); /* coded frame size */
     230        ast->coded_framesize = avio_rb32(pb); /* coded frame size */
    161231        avio_rb32(pb); /* ??? */
    162232        avio_rb32(pb); /* ??? */
    163233        avio_rb32(pb); /* ??? */
    164         ast->sub_packet_h = sub_packet_h = avio_rb16(pb); /* 1 */
     234        ast->sub_packet_h = avio_rb16(pb); /* 1 */
    165235        st->codec->block_align= avio_rb16(pb); /* frame size */
    166         ast->sub_packet_size = sub_packet_size = avio_rb16(pb); /* sub packet size */
     236        ast->sub_packet_size = avio_rb16(pb); /* sub packet size */
    167237        avio_rb16(pb); /* ??? */
    168238        if (version == 5) {
    169             avio_rb16(pb); avio_rb16(pb); avio_rb16(pb);
     239            avio_rb16(pb);
     240            avio_rb16(pb);
     241            avio_rb16(pb);
    170242        }
    171243        st->codec->sample_rate = avio_rb16(pb);
    172         avio_rb32(pb);
     244        avio_rb16(pb); /* ??? */
     245        avio_rb16(pb); /* sample size */
    173246        st->codec->channels = avio_rb16(pb);
    174247        if (version == 5) {
    175248            avio_rb32(pb);
    static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,  
    177250            buf[4] = 0;
    178251        } else {
    179252            get_str8(pb, buf, sizeof(buf)); /* desc */
    180             get_str8(pb, buf, sizeof(buf)); /* desc */
     253            get_str8(pb, buf, sizeof(buf)); /* FOURCC */
    181254        }
    182255        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
    183256        st->codec->codec_tag  = AV_RL32(buf);
    static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,  
    190263        case CODEC_ID_RA_288:
    191264            st->codec->extradata_size= 0;
    192265            ast->audio_framesize = st->codec->block_align;
    193             st->codec->block_align = coded_framesize;
     266            st->codec->block_align = ast->coded_framesize;
    194267
    195             if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
     268            if(ast->audio_framesize >= UINT_MAX / ast->sub_packet_h){
    196269                av_log(s, AV_LOG_ERROR, "ast->audio_framesize * sub_packet_h too large\n");
    197270                return -1;
    198271            }
    199272
    200             av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h);
     273            av_new_packet(&ast->pkt, ast->audio_framesize * ast->sub_packet_h);
    201274            break;
    202275        case CODEC_ID_COOK:
    203276        case CODEC_ID_ATRAC3:
    static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,  
    220293                }
    221294                st->codec->block_align = ff_sipr_subpk_size[flavor];
    222295            } else {
    223                 if(sub_packet_size <= 0){
     296                if(ast->sub_packet_size <= 0){
    224297                    av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n");
    225298                    return -1;
    226299                }
    static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,  
    229302            if ((ret = rm_read_extradata(pb, st->codec, codecdata_length)) < 0)
    230303                return ret;
    231304
    232             if(ast->audio_framesize >= UINT_MAX / sub_packet_h){
     305            if(ast->audio_framesize >= UINT_MAX / ast->sub_packet_h){
    233306                av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n");
    234307                return -1;
    235308            }
    236309
    237             av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h);
     310            av_new_packet(&ast->pkt, ast->audio_framesize * ast->sub_packet_h);
    238311            break;
    239312        case CODEC_ID_AAC:
    240313            avio_rb16(pb); avio_r8(pb);
    ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb,  
    281354        if (rm_read_audio_stream_info(s, pb, st, rst, 0))
    282355            return -1;
    283356    } else {
    284         int fps, fps2;
     357        int gcd, fps;
    285358        if (avio_rl32(pb) != MKTAG('V', 'I', 'D', 'O')) {
    286359        fail1:
    287360            av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n");
     361            st->codec->codec_id = CODEC_ID_NONE;
    288362            goto skip;
    289363        }
    290364        st->codec->codec_tag = avio_rl32(pb);
    ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb,  
    296370        st->codec->width = avio_rb16(pb);
    297371        st->codec->height = avio_rb16(pb);
    298372        st->codec->time_base.num= 1 << 16;
    299         fps= avio_rb16(pb);
     373        avio_rb16(pb); /* bpp */
    300374        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
    301375        avio_rb32(pb);
    302         fps2= avio_rb32(pb);
     376        fps= avio_rb32(pb);
    303377
    304378        if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (avio_tell(pb) - codec_pos))) < 0)
    305379            return ret;
    306380
    307381//        av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
    308         st->codec->time_base.den = fps2;
     382        st->codec->time_base.den = fps;
     383        gcd = av_gcd(st->codec->time_base.num, st->codec->time_base.den);
     384        st->codec->time_base.num /= gcd;
     385        st->codec->time_base.den /= gcd;
    309386        //XXX: do we really need that?
    310387        switch(st->codec->extradata[4]>>4){
    311388        case 1: st->codec->codec_id = CODEC_ID_RV10; break;
    skip:  
    370447    return 0;
    371448}
    372449
     450/* audio data is CBR */
    373451static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap)
    374452{
    375453    RMDemuxContext *rm = s->priv_data;
    static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)  
    388466    RMDemuxContext *rm = s->priv_data;
    389467    AVStream *st;
    390468    AVIOContext *pb = s->pb;
    391     unsigned int tag;
     469    unsigned int tag, head_size;
    392470    int tag_size;
    393     unsigned int start_time, duration;
    394471    unsigned int data_off = 0, indx_off = 0;
    395472    char buf[128];
    396473    int flags = 0;
    static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)  
    403480        return AVERROR(EIO);
    404481    }
    405482
    406     avio_rb32(pb); /* header size */
    407     avio_rb16(pb);
    408     avio_rb32(pb);
     483    head_size = avio_rb32(pb); /* header size */
     484    avio_rb16(pb); /* chunk version */
     485    /* file version */
     486    if(0x12 == head_size)
     487        avio_rb32(pb);
     488    else
     489        avio_rb16(pb);
    409490    avio_rb32(pb); /* number of headers */
    410491
    411492    for(;;) {
    static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)  
    413494            return -1;
    414495        tag = avio_rl32(pb);
    415496        tag_size = avio_rb32(pb);
    416         avio_rb16(pb);
     497        avio_rb16(pb); /* version */
    417498#if 0
    418499        printf("tag=%c%c%c%c (%08x) size=%d\n",
    419500               (tag) & 0xff,
    static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)  
    433514            avio_rb32(pb); /* max packet size */
    434515            avio_rb32(pb); /* avg packet size */
    435516            avio_rb32(pb); /* nb packets */
    436             avio_rb32(pb); /* duration */
    437             avio_rb32(pb); /* preroll */
    438             indx_off = avio_rb32(pb); /* index offset */
    439             data_off = avio_rb32(pb); /* data offset */
     517            avio_rb32(pb); /* duration in ms */
     518            avio_rb32(pb); /* preroll in ms */
     519            indx_off = avio_rb32(pb); /* the first index offset */
     520            data_off = avio_rb32(pb); /* the first data offset */
    440521            avio_rb16(pb); /* nb streams */
    441522            flags = avio_rb16(pb); /* flags */
    442523            break;
    static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap)  
    449530                return AVERROR(ENOMEM);
    450531            st->id = avio_rb16(pb);
    451532            avio_rb32(pb); /* max bit rate */
    452             st->codec->bit_rate = avio_rb32(pb); /* bit rate */
     533            st->codec->bit_rate = avio_rb32(pb); /* avg bit rate */
    453534            avio_rb32(pb); /* max packet size */
    454535            avio_rb32(pb); /* avg packet size */
    455             start_time = avio_rb32(pb); /* start time */
    456             avio_rb32(pb); /* preroll */
    457             duration = avio_rb32(pb); /* duration */
    458             st->start_time = start_time;
    459             st->duration = duration;
     536            st->start_time = avio_rb32(pb); /* start time in ms */
     537            avio_rb32(pb); /* preroll in ms */
     538            st->duration = avio_rb32(pb); /* duration in ms */
    460539            get_str8(pb, buf, sizeof(buf)); /* desc */
    461540            get_str8(pb, buf, sizeof(buf)); /* mimetype */
    462541            st->codec->codec_type = AVMEDIA_TYPE_DATA;
    ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,  
    786865    pkt->pts= timestamp;
    787866    if (flags & 2)
    788867        pkt->flags |= AV_PKT_FLAG_KEY;
     868    if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
     869        process_video_timestamp(rm,st->codec->codec_tag,pkt);
    789870
    790871    return st->codec->codec_type == AVMEDIA_TYPE_AUDIO ? rm->audio_pkt_cnt : 0;
    791872}
    ff_rm_retrieve_cache (AVFormatContext *s, AVIOContext *pb,  
    809890    rm->audio_pkt_cnt--;
    810891    if ((pkt->pts = ast->audiotimestamp) != AV_NOPTS_VALUE) {
    811892        ast->audiotimestamp = AV_NOPTS_VALUE;
    812         pkt->flags = AV_PKT_FLAG_KEY;
     893        pkt->flags |= AV_PKT_FLAG_KEY;
    813894    } else
    814         pkt->flags = 0;
     895        pkt->flags &= (~AV_PKT_FLAG_KEY);
    815896    pkt->stream_index = st->index;
    816897
    817898    return rm->audio_pkt_cnt;
    static int64_t rm_read_dts(AVFormatContext *s, int stream_index,  
    9341015        avio_skip(s->pb, len);
    9351016    }
    9361017    *ppos = pos;
     1018    rm->video_after_seek = 1;
    9371019    return dts;
    9381020}
    9391021