changeset 1484:20438d25cf8c libavformat

fix timestamp rounding in syncpoints index reading (unfinished and disabled)
author michael
date Sun, 12 Nov 2006 12:07:42 +0000
parents 6f36ee726e5c
children 9000f9cdac49
files nutdec.c
diffstat 1 files changed, 103 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/nutdec.c	Sun Nov 12 06:10:21 2006 +0000
+++ b/nutdec.c	Sun Nov 12 12:07:42 2006 +0000
@@ -199,7 +199,7 @@
 
 static int skip_reserved(ByteIOContext *bc, int64_t pos){
     pos -= url_ftell(bc);
-
+av_log(NULL, AV_LOG_ERROR, "skip %d\n", (int)pos);
     if(pos<0){
         url_fseek(bc, pos, SEEK_CUR);
         return -1;
@@ -459,7 +459,11 @@
 
     time_base= nut->time_base[tmp % nut->time_base_count];
     for(i=0; i<s->nb_streams; i++){
-        nut->stream[i].last_pts= av_rescale_q(tmp / nut->time_base_count, time_base, nut->stream[i].time_base); //FIXME rounding and co
+        nut->stream[i].last_pts= av_rescale_rnd(
+            tmp / nut->time_base_count,
+            time_base.num * (int64_t)nut->stream[i].time_base.den,
+            time_base.den * (int64_t)nut->stream[i].time_base.num,
+            AV_ROUND_DOWN);
         //last_key_frame ?
     }
     //FIXME put this in a reset func maybe
@@ -471,6 +475,96 @@
     return 0;
 }
 
+static int find_and_decode_index(NUTContext *nut){
+    AVFormatContext *s= nut->avf;
+    ByteIOContext *bc = &s->pb;
+    uint64_t tmp, end;
+    int i, j, syncpoint_count;
+    int64_t filesize= url_fsize(bc);
+    int64_t *syncpoints;
+    int8_t *has_keyframe;
+
+    url_fseek(bc, filesize-12, SEEK_SET);
+    url_fseek(bc, filesize-get_be64(bc), SEEK_SET);
+    if(get_be64(bc) != INDEX_STARTCODE){
+        av_log(s, AV_LOG_ERROR, "no index at the end\n");
+        return -1;
+    }
+
+    end= get_packetheader(nut, bc, 1);
+    end += url_ftell(bc) - 4;
+
+    get_v(bc); //max_pts
+    GET_V(syncpoint_count, tmp < INT_MAX/8 && tmp > 0)
+    syncpoints= av_malloc(sizeof(int64_t)*syncpoint_count);
+    has_keyframe= av_malloc(sizeof(int8_t)*(syncpoint_count+1));
+    for(i=0; i<syncpoint_count; i++){
+        GET_V(syncpoints[i], tmp>0)
+        if(i)
+            syncpoints[i] += syncpoints[i-1];
+    }
+
+    for(i=0; i<s->nb_streams; i++){
+        int64_t last_pts= -1;
+        for(j=0; j<syncpoint_count;){
+            uint64_t x= get_v(bc);
+            int type= x&1;
+            int n= j;
+            x>>=1;
+            if(type){
+                int flag= x&1;
+                x>>=1;
+                if(n+x >= syncpoint_count + 1){
+                    av_log(s, AV_LOG_ERROR, "index overflow A\n");
+                    return -1;
+                }
+                while(x--)
+                    has_keyframe[n++]= flag;
+                has_keyframe[n++]= !flag;
+            }else{
+                while(x != 1){
+                    if(n>=syncpoint_count + 1){
+                        av_log(s, AV_LOG_ERROR, "index overflow B\n");
+                        return -1;
+                    }
+                    has_keyframe[n++]= x&1;
+                    x>>=1;
+                }
+            }
+            if(has_keyframe[0]){
+                av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n");
+                return -1;
+            }
+            assert(n<=syncpoint_count+1);
+            for(; j<n; j++){
+                if(has_keyframe[j]){
+                    uint64_t B, A= get_v(bc);
+                    if(!A){
+                        A= get_v(bc);
+                        B= get_v(bc);
+                        //eor_pts[j][i] = last_pts + A + B
+                    }else
+                        B= 0;
+                    av_add_index_entry(
+                        s->streams[i],
+                        16*syncpoints[j-1],
+                        last_pts + A,
+                        0,
+                        0,
+                        AVINDEX_KEYFRAME);
+                    last_pts += A + B;
+                }
+            }
+        }
+    }
+
+    if(skip_reserved(bc, end) || check_checksum(bc)){
+        av_log(s, AV_LOG_ERROR, "Index checksum mismatch\n");
+        return -1;
+    }
+    return 0;
+}
+
 static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
 {
     NUTContext *nut = s->priv_data;
@@ -523,6 +617,13 @@
 
     s->data_offset= pos-8;
 
+    if(0 &&!url_is_streamed(bc)){
+        int64_t orig_pos= url_ftell(bc);
+        find_and_decode_index(nut);
+        url_fseek(bc, orig_pos, SEEK_SET);
+    }
+    assert(nut->next_startcode == SYNCPOINT_STARTCODE);
+
     return 0;
 }