changeset 418:41da3366d341 libavformat

checksuming for nut & nice checksum API for libavformat
author michael
date Mon, 05 Apr 2004 12:02:10 +0000
parents 5a89e49ff688
children 51c25922a543
files avio.h aviobuf.c crc.c nut.c
diffstat 4 files changed, 83 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/avio.h	Mon Apr 05 11:36:13 2004 +0000
+++ b/avio.h	Mon Apr 05 12:02:10 2004 +0000
@@ -78,6 +78,9 @@
     int write_flag;  /* true if open for writing */
     int is_streamed;
     int max_packet_size;
+    unsigned long checksum;
+    unsigned char *checksum_ptr;
+    unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
 } ByteIOContext;
 
 int init_put_byte(ByteIOContext *s,
@@ -150,6 +153,10 @@
 int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size);
 int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer);
 
+unsigned long get_checksum(ByteIOContext *s);
+void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum);
+unsigned long update_adler32(unsigned long adler, const uint8_t *buf, unsigned int len);
+
 /* file.c */
 extern URLProtocol file_protocol;
 extern URLProtocol pipe_protocol;
--- a/aviobuf.c	Mon Apr 05 11:36:13 2004 +0000
+++ b/aviobuf.c	Mon Apr 05 12:02:10 2004 +0000
@@ -48,6 +48,8 @@
     s->eof_reached = 0;
     s->is_streamed = 0;
     s->max_packet_size = 0;
+    s->checksum_ptr= NULL;
+    s->update_checksum= NULL;
     return 0;
 }
                   
@@ -58,6 +60,10 @@
     if (s->buf_ptr > s->buffer) {
         if (s->write_packet)
             s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
+        if(s->checksum_ptr){
+            s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
+            s->checksum_ptr= s->buffer;
+        }
         s->pos += s->buf_ptr - s->buffer;
     }
     s->buf_ptr = s->buffer;
@@ -243,6 +249,12 @@
     /* no need to do anything if EOF already reached */
     if (s->eof_reached)
         return;
+
+    if(s->checksum_ptr){
+        s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
+        s->checksum_ptr= s->buffer;
+    }
+
     len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
     if (len <= 0) {
         /* do not modify buffer if EOF reached so that a seek back can
@@ -255,6 +267,18 @@
     }
 }
 
+unsigned long get_checksum(ByteIOContext *s){
+    s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
+    s->checksum_ptr= NULL;
+    return s->checksum;
+}
+
+void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum){
+    s->update_checksum= update_checksum;
+    s->checksum= s->update_checksum(checksum, NULL, 0);
+    s->checksum_ptr= s->buf_ptr;
+}
+
 /* NOTE: return 0 if EOF, so you cannot use it if EOF handling is
    necessary */
 /* XXX: put an inline version */
--- a/crc.c	Mon Apr 05 11:36:13 2004 +0000
+++ b/crc.c	Mon Apr 05 12:02:10 2004 +0000
@@ -33,7 +33,7 @@
 #define DO8(buf)  DO4(buf); DO4(buf);
 #define DO16(buf) DO8(buf); DO8(buf);
 
-static uint32_t adler32(uint32_t adler, const uint8_t *buf, unsigned int len)
+unsigned long update_adler32(unsigned long adler, const uint8_t *buf, unsigned int len)
 {
     unsigned long s1 = adler & 0xffff;
     unsigned long s2 = (adler >> 16) & 0xffff;
@@ -66,7 +66,7 @@
     CRCState *crc = s->priv_data;
 
     /* init CRC */
-    crc->crcval = adler32(0, NULL, 0);
+    crc->crcval = update_adler32(0, NULL, 0);
 
     return 0;
 }
@@ -76,7 +76,7 @@
                             const uint8_t *buf, int size, int64_t pts)
 {
     CRCState *crc = s->priv_data;
-    crc->crcval = adler32(crc->crcval, buf, size);
+    crc->crcval = update_adler32(crc->crcval, buf, size);
     return 0;
 }
 
--- a/nut.c	Mon Apr 05 11:36:13 2004 +0000
+++ b/nut.c	Mon Apr 05 12:02:10 2004 +0000
@@ -25,7 +25,6 @@
 
 /*
  * TODO:
- * - checksumming
  * - seeking
  * - index writing
  * - index packet reading support
@@ -284,7 +283,7 @@
         return 0;
 }
 
-static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_length)
+static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_length, int calculate_checksum)
 {
     int64_t start, size, last_size;
     start= url_ftell(bc) - prefix_length;
@@ -293,6 +292,9 @@
         av_log(nut->avf, AV_LOG_ERROR, "get_packetheader called at weird position\n");
         return -1;
     }
+    
+    if(calculate_checksum)
+        init_checksum(bc, update_adler32, 0);
 
     size= get_v(bc);
     last_size= get_v(bc);
@@ -308,6 +310,11 @@
     return size;
 }
 
+static int check_checksum(ByteIOContext *bc){
+    unsigned long checksum= get_checksum(bc);
+    return checksum != get_be32(bc);
+}
+
 /**
  * 
  */
@@ -352,13 +359,16 @@
     return 0;
 }
 
-static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size)
+static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum)
 {
     put_flush_packet(bc);
     nut->last_packet_start= nut->packet_start;
     nut->packet_start+= nut->written_packet_size;
     nut->packet_size_pos = url_ftell(bc);
     nut->written_packet_size = max_size;
+    
+    if(calculate_checksum)
+        init_checksum(bc, update_adler32, 0);
 
     /* packet header */
     put_v(bc, nut->written_packet_size); /* forward ptr */
@@ -367,11 +377,14 @@
     return 0;
 }
 
-static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size){
+static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){
     int64_t start= nut->packet_start;
     int64_t cur= url_ftell(bc);
     int size= cur - start + additional_size;
     
+    if(calculate_checksum)
+        size += 4;
+    
     if(size != nut->written_packet_size){
         int i;
 
@@ -384,6 +397,9 @@
 
         url_fseek(bc, cur, SEEK_SET);
         nut->written_packet_size= size; //FIXME may fail if multiple updates with differing sizes, as get_length may differ
+        
+        if(calculate_checksum)
+            put_be32(bc, get_checksum(bc));
     }
     
     return 0;
@@ -405,10 +421,10 @@
     
     /* main header */
     put_be64(bc, MAIN_STARTCODE);
-    put_packetheader(nut, bc, 120+5*256);
+    put_packetheader(nut, bc, 120+5*256, 1);
     put_v(bc, 1); /* version */
     put_v(bc, s->nb_streams);
-    put_v(bc, 3); /* checksum threshold */
+    put_v(bc, 3);
     
     build_frame_code(s);
     assert(nut->frame_code['N'].flags == 1);
@@ -435,9 +451,7 @@
         put_v(bc, j);
     }
 
-    put_be32(bc, 0); /* FIXME: checksum */
-    
-    update_packetheader(nut, bc, 0);
+    update_packetheader(nut, bc, 0, 1);
     
     /* stream headers */
     for (i = 0; i < s->nb_streams; i++)
@@ -447,7 +461,7 @@
 	codec = &s->streams[i]->codec;
 	
 	put_be64(bc, STREAM_STARTCODE);
-	put_packetheader(nut, bc, 120 + codec->extradata_size);
+	put_packetheader(nut, bc, 120 + codec->extradata_size, 1);
 	put_v(bc, i /*s->streams[i]->index*/);
 	put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);
 	if (codec->codec_tag)
@@ -520,14 +534,13 @@
             default:
                 break;
 	}
-	put_be32(bc, 0); /* FIXME: checksum */
-        update_packetheader(nut, bc, 0);
+        update_packetheader(nut, bc, 0, 1);
     }
 
     /* info header */
     put_be64(bc, INFO_STARTCODE);
     put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+
-        strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT)); 
+        strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT), 1); 
     if (s->author[0])
     {
         put_v(bc, 9); /* type */
@@ -553,9 +566,7 @@
     put_str(bc, LIBAVFORMAT_IDENT);
     
     put_v(bc, 0); /* eof info */
-
-    put_be32(bc, 0); /* FIXME: checksum */
-    update_packetheader(nut, bc, 0);
+    update_packetheader(nut, bc, 0, 1);
         
     put_flush_packet(bc);
     
@@ -594,7 +605,7 @@
     }
 
     if(frame_type>0){
-        update_packetheader(nut, bc, 0);
+        update_packetheader(nut, bc, 0, 0);
         reset(s);
         full_pts=1;
     }
@@ -684,7 +695,7 @@
     put_byte(bc, frame_code);
 
     if(frame_type>0)
-        put_packetheader(nut, bc, FFMAX(size+20, MAX_TYPE1_DISTANCE));
+        put_packetheader(nut, bc, FFMAX(size+20, MAX_TYPE1_DISTANCE), 0);
     if(nut->frame_code[frame_code].stream_id_plus1 == 0)
         put_v(bc, stream_index);
     if (flags & FLAG_PTS){
@@ -697,7 +708,7 @@
         put_v(bc, size / size_mul);
     if(size > MAX_TYPE1_DISTANCE){
         assert(frame_type > 0);
-        update_packetheader(nut, bc, size);
+        update_packetheader(nut, bc, size, 0);
     }
     
     put_buffer(bc, buf, size);
@@ -712,7 +723,7 @@
     NUTContext *nut = s->priv_data;
     ByteIOContext *bc = &s->pb;
 
-    update_packetheader(nut, bc, 0);
+    update_packetheader(nut, bc, 0, 0);
 
 #if 0
     int i;
@@ -722,11 +733,10 @@
     for (i = 0; s->nb_streams; i++)
     {
 	put_be64(bc, INDEX_STARTCODE);
-	put_packetheader(nut, bc, 64);
+	put_packetheader(nut, bc, 64, 1);
 	put_v(bc, s->streams[i]->id);
 	put_v(bc, ...);
-	put_be32(bc, 0); /* FIXME: checksum */
-        update_packetheader(nut, bc, 0);
+        update_packetheader(nut, bc, 0, 1);
     }
 #endif
 
@@ -768,7 +778,7 @@
     tmp = get_be64(bc);
     if (tmp != MAIN_STARTCODE)
 	av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp);
-    get_packetheader(nut, bc, 8);
+    get_packetheader(nut, bc, 8, 1);
     
     tmp = get_v(bc);
     if (tmp != 1)
@@ -821,7 +831,10 @@
         return -1;
     }
     
-    get_be32(bc); /* checkusm */
+    if(check_checksum(bc)){
+        av_log(s, AV_LOG_ERROR, "Main header checksum missmatch\n");
+        return -1;
+    }
     
     s->bit_rate = 0;
 
@@ -836,7 +849,7 @@
 	tmp = get_be64(bc);
 	if (tmp != STREAM_STARTCODE)
 	    av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp);
-	get_packetheader(nut, bc, 8);
+	get_packetheader(nut, bc, 8, 1);
 	st = av_new_stream(s, get_v(bc));
 	if (!st)
 	    return AVERROR_NOMEM;
@@ -895,14 +908,17 @@
 	    st->codec.sample_rate = (get_v(bc) * nom) / denom;
 	    st->codec.channels = get_v(bc);
 	}
-        get_be32(bc); /* checksum */
+        if(check_checksum(bc)){
+            av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", cur_stream);
+            return -1;
+        }
         nut->stream[cur_stream].rate_num= nom;
         nut->stream[cur_stream].rate_den= denom;
     }
         
     tmp = get_be64(bc);
     if (tmp == INFO_STARTCODE){
-	get_packetheader(nut, bc, 8);
+	get_packetheader(nut, bc, 8, 1);
     
         for(;;){
             int id= get_v(bc);
@@ -943,7 +959,9 @@
                     get_str(bc, NULL, 0);
             }
         }
-        get_be32(bc); /* checksum */
+        if(check_checksum(bc)){
+            av_log(s, AV_LOG_ERROR, "Info header checksum missmatch\n");
+        }
     }else
         url_fseek(bc, -8, SEEK_CUR);
     
@@ -986,9 +1004,9 @@
     if(flags & FLAG_FRAME_TYPE){
         reset(s);
         if(frame_type==2){
-            get_packetheader(nut, bc, 8+1);
+            get_packetheader(nut, bc, 8+1, 0);
         }else{
-            get_packetheader(nut, bc, 1);
+            get_packetheader(nut, bc, 1, 0);
             frame_type= 1;
         }
     }