Commit ee9f36a8 authored by Michael Niedermayer's avatar Michael Niedermayer

checksuming for nut & nice checksum API for libavformat

Originally committed as revision 2969 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 5e9b83f5
...@@ -78,6 +78,9 @@ typedef struct { ...@@ -78,6 +78,9 @@ typedef struct {
int write_flag; /* true if open for writing */ int write_flag; /* true if open for writing */
int is_streamed; int is_streamed;
int max_packet_size; 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; } ByteIOContext;
int init_put_byte(ByteIOContext *s, int init_put_byte(ByteIOContext *s,
...@@ -150,6 +153,10 @@ int url_open_dyn_buf(ByteIOContext *s); ...@@ -150,6 +153,10 @@ int url_open_dyn_buf(ByteIOContext *s);
int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size); int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size);
int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer); 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 */ /* file.c */
extern URLProtocol file_protocol; extern URLProtocol file_protocol;
extern URLProtocol pipe_protocol; extern URLProtocol pipe_protocol;
......
...@@ -48,6 +48,8 @@ int init_put_byte(ByteIOContext *s, ...@@ -48,6 +48,8 @@ int init_put_byte(ByteIOContext *s,
s->eof_reached = 0; s->eof_reached = 0;
s->is_streamed = 0; s->is_streamed = 0;
s->max_packet_size = 0; s->max_packet_size = 0;
s->checksum_ptr= NULL;
s->update_checksum= NULL;
return 0; return 0;
} }
...@@ -58,6 +60,10 @@ static void flush_buffer(ByteIOContext *s) ...@@ -58,6 +60,10 @@ static void flush_buffer(ByteIOContext *s)
if (s->buf_ptr > s->buffer) { if (s->buf_ptr > s->buffer) {
if (s->write_packet) if (s->write_packet)
s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); 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->pos += s->buf_ptr - s->buffer;
} }
s->buf_ptr = s->buffer; s->buf_ptr = s->buffer;
...@@ -243,6 +249,12 @@ static void fill_buffer(ByteIOContext *s) ...@@ -243,6 +249,12 @@ static void fill_buffer(ByteIOContext *s)
/* no need to do anything if EOF already reached */ /* no need to do anything if EOF already reached */
if (s->eof_reached) if (s->eof_reached)
return; 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); len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
if (len <= 0) { if (len <= 0) {
/* do not modify buffer if EOF reached so that a seek back can /* do not modify buffer if EOF reached so that a seek back can
...@@ -255,6 +267,18 @@ static void fill_buffer(ByteIOContext *s) ...@@ -255,6 +267,18 @@ static void fill_buffer(ByteIOContext *s)
} }
} }
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 /* NOTE: return 0 if EOF, so you cannot use it if EOF handling is
necessary */ necessary */
/* XXX: put an inline version */ /* XXX: put an inline version */
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#define DO8(buf) DO4(buf); DO4(buf); #define DO8(buf) DO4(buf); DO4(buf);
#define DO16(buf) DO8(buf); DO8(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 s1 = adler & 0xffff;
unsigned long s2 = (adler >> 16) & 0xffff; unsigned long s2 = (adler >> 16) & 0xffff;
...@@ -66,7 +66,7 @@ static int crc_write_header(struct AVFormatContext *s) ...@@ -66,7 +66,7 @@ static int crc_write_header(struct AVFormatContext *s)
CRCState *crc = s->priv_data; CRCState *crc = s->priv_data;
/* init CRC */ /* init CRC */
crc->crcval = adler32(0, NULL, 0); crc->crcval = update_adler32(0, NULL, 0);
return 0; return 0;
} }
...@@ -76,7 +76,7 @@ static int crc_write_packet(struct AVFormatContext *s, ...@@ -76,7 +76,7 @@ static int crc_write_packet(struct AVFormatContext *s,
const uint8_t *buf, int size, int64_t pts) const uint8_t *buf, int size, int64_t pts)
{ {
CRCState *crc = s->priv_data; CRCState *crc = s->priv_data;
crc->crcval = adler32(crc->crcval, buf, size); crc->crcval = update_adler32(crc->crcval, buf, size);
return 0; return 0;
} }
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
/* /*
* TODO: * TODO:
* - checksumming
* - seeking * - seeking
* - index writing * - index writing
* - index packet reading support * - index packet reading support
...@@ -284,7 +283,7 @@ static int get_str(ByteIOContext *bc, char *string, int maxlen){ ...@@ -284,7 +283,7 @@ static int get_str(ByteIOContext *bc, char *string, int maxlen){
return 0; 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; int64_t start, size, last_size;
start= url_ftell(bc) - prefix_length; start= url_ftell(bc) - prefix_length;
...@@ -294,6 +293,9 @@ static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_lengt ...@@ -294,6 +293,9 @@ static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_lengt
return -1; return -1;
} }
if(calculate_checksum)
init_checksum(bc, update_adler32, 0);
size= get_v(bc); size= get_v(bc);
last_size= get_v(bc); last_size= get_v(bc);
if(nut->written_packet_size != last_size){ if(nut->written_packet_size != last_size){
...@@ -308,6 +310,11 @@ static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_lengt ...@@ -308,6 +310,11 @@ static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_lengt
return size; return size;
} }
static int check_checksum(ByteIOContext *bc){
unsigned long checksum= get_checksum(bc);
return checksum != get_be32(bc);
}
/** /**
* *
*/ */
...@@ -352,7 +359,7 @@ static int put_str(ByteIOContext *bc, const char *string){ ...@@ -352,7 +359,7 @@ static int put_str(ByteIOContext *bc, const char *string){
return 0; 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); put_flush_packet(bc);
nut->last_packet_start= nut->packet_start; nut->last_packet_start= nut->packet_start;
...@@ -360,6 +367,9 @@ static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size) ...@@ -360,6 +367,9 @@ static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size)
nut->packet_size_pos = url_ftell(bc); nut->packet_size_pos = url_ftell(bc);
nut->written_packet_size = max_size; nut->written_packet_size = max_size;
if(calculate_checksum)
init_checksum(bc, update_adler32, 0);
/* packet header */ /* packet header */
put_v(bc, nut->written_packet_size); /* forward ptr */ put_v(bc, nut->written_packet_size); /* forward ptr */
put_v(bc, nut->packet_start - nut->last_packet_start); /* backward ptr */ put_v(bc, nut->packet_start - nut->last_packet_start); /* backward ptr */
...@@ -367,11 +377,14 @@ static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size) ...@@ -367,11 +377,14 @@ static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size)
return 0; 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 start= nut->packet_start;
int64_t cur= url_ftell(bc); int64_t cur= url_ftell(bc);
int size= cur - start + additional_size; int size= cur - start + additional_size;
if(calculate_checksum)
size += 4;
if(size != nut->written_packet_size){ if(size != nut->written_packet_size){
int i; int i;
...@@ -384,6 +397,9 @@ static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additiona ...@@ -384,6 +397,9 @@ static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additiona
url_fseek(bc, cur, SEEK_SET); 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 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; return 0;
...@@ -405,10 +421,10 @@ static int nut_write_header(AVFormatContext *s) ...@@ -405,10 +421,10 @@ static int nut_write_header(AVFormatContext *s)
/* main header */ /* main header */
put_be64(bc, MAIN_STARTCODE); 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, 1); /* version */
put_v(bc, s->nb_streams); put_v(bc, s->nb_streams);
put_v(bc, 3); /* checksum threshold */ put_v(bc, 3);
build_frame_code(s); build_frame_code(s);
assert(nut->frame_code['N'].flags == 1); assert(nut->frame_code['N'].flags == 1);
...@@ -435,9 +451,7 @@ static int nut_write_header(AVFormatContext *s) ...@@ -435,9 +451,7 @@ static int nut_write_header(AVFormatContext *s)
put_v(bc, j); put_v(bc, j);
} }
put_be32(bc, 0); /* FIXME: checksum */ update_packetheader(nut, bc, 0, 1);
update_packetheader(nut, bc, 0);
/* stream headers */ /* stream headers */
for (i = 0; i < s->nb_streams; i++) for (i = 0; i < s->nb_streams; i++)
...@@ -447,7 +461,7 @@ static int nut_write_header(AVFormatContext *s) ...@@ -447,7 +461,7 @@ static int nut_write_header(AVFormatContext *s)
codec = &s->streams[i]->codec; codec = &s->streams[i]->codec;
put_be64(bc, STREAM_STARTCODE); 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, i /*s->streams[i]->index*/);
put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0); put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0);
if (codec->codec_tag) if (codec->codec_tag)
...@@ -520,14 +534,13 @@ static int nut_write_header(AVFormatContext *s) ...@@ -520,14 +534,13 @@ static int nut_write_header(AVFormatContext *s)
default: default:
break; break;
} }
put_be32(bc, 0); /* FIXME: checksum */ update_packetheader(nut, bc, 0, 1);
update_packetheader(nut, bc, 0);
} }
/* info header */ /* info header */
put_be64(bc, INFO_STARTCODE); put_be64(bc, INFO_STARTCODE);
put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+ 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]) if (s->author[0])
{ {
put_v(bc, 9); /* type */ put_v(bc, 9); /* type */
...@@ -553,9 +566,7 @@ static int nut_write_header(AVFormatContext *s) ...@@ -553,9 +566,7 @@ static int nut_write_header(AVFormatContext *s)
put_str(bc, LIBAVFORMAT_IDENT); put_str(bc, LIBAVFORMAT_IDENT);
put_v(bc, 0); /* eof info */ put_v(bc, 0); /* eof info */
update_packetheader(nut, bc, 0, 1);
put_be32(bc, 0); /* FIXME: checksum */
update_packetheader(nut, bc, 0);
put_flush_packet(bc); put_flush_packet(bc);
...@@ -594,7 +605,7 @@ static int nut_write_packet(AVFormatContext *s, int stream_index, ...@@ -594,7 +605,7 @@ static int nut_write_packet(AVFormatContext *s, int stream_index,
} }
if(frame_type>0){ if(frame_type>0){
update_packetheader(nut, bc, 0); update_packetheader(nut, bc, 0, 0);
reset(s); reset(s);
full_pts=1; full_pts=1;
} }
...@@ -684,7 +695,7 @@ static int nut_write_packet(AVFormatContext *s, int stream_index, ...@@ -684,7 +695,7 @@ static int nut_write_packet(AVFormatContext *s, int stream_index,
put_byte(bc, frame_code); put_byte(bc, frame_code);
if(frame_type>0) 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) if(nut->frame_code[frame_code].stream_id_plus1 == 0)
put_v(bc, stream_index); put_v(bc, stream_index);
if (flags & FLAG_PTS){ if (flags & FLAG_PTS){
...@@ -697,7 +708,7 @@ static int nut_write_packet(AVFormatContext *s, int stream_index, ...@@ -697,7 +708,7 @@ static int nut_write_packet(AVFormatContext *s, int stream_index,
put_v(bc, size / size_mul); put_v(bc, size / size_mul);
if(size > MAX_TYPE1_DISTANCE){ if(size > MAX_TYPE1_DISTANCE){
assert(frame_type > 0); assert(frame_type > 0);
update_packetheader(nut, bc, size); update_packetheader(nut, bc, size, 0);
} }
put_buffer(bc, buf, size); put_buffer(bc, buf, size);
...@@ -712,7 +723,7 @@ static int nut_write_trailer(AVFormatContext *s) ...@@ -712,7 +723,7 @@ static int nut_write_trailer(AVFormatContext *s)
NUTContext *nut = s->priv_data; NUTContext *nut = s->priv_data;
ByteIOContext *bc = &s->pb; ByteIOContext *bc = &s->pb;
update_packetheader(nut, bc, 0); update_packetheader(nut, bc, 0, 0);
#if 0 #if 0
int i; int i;
...@@ -722,11 +733,10 @@ static int nut_write_trailer(AVFormatContext *s) ...@@ -722,11 +733,10 @@ static int nut_write_trailer(AVFormatContext *s)
for (i = 0; s->nb_streams; i++) for (i = 0; s->nb_streams; i++)
{ {
put_be64(bc, INDEX_STARTCODE); 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, s->streams[i]->id);
put_v(bc, ...); put_v(bc, ...);
put_be32(bc, 0); /* FIXME: checksum */ update_packetheader(nut, bc, 0, 1);
update_packetheader(nut, bc, 0);
} }
#endif #endif
...@@ -768,7 +778,7 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -768,7 +778,7 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
tmp = get_be64(bc); tmp = get_be64(bc);
if (tmp != MAIN_STARTCODE) if (tmp != MAIN_STARTCODE)
av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp); 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); tmp = get_v(bc);
if (tmp != 1) if (tmp != 1)
...@@ -821,7 +831,10 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -821,7 +831,10 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
return -1; 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; s->bit_rate = 0;
...@@ -836,7 +849,7 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -836,7 +849,7 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
tmp = get_be64(bc); tmp = get_be64(bc);
if (tmp != STREAM_STARTCODE) if (tmp != STREAM_STARTCODE)
av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp); 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)); st = av_new_stream(s, get_v(bc));
if (!st) if (!st)
return AVERROR_NOMEM; return AVERROR_NOMEM;
...@@ -895,14 +908,17 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -895,14 +908,17 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec.sample_rate = (get_v(bc) * nom) / denom; st->codec.sample_rate = (get_v(bc) * nom) / denom;
st->codec.channels = get_v(bc); 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_num= nom;
nut->stream[cur_stream].rate_den= denom; nut->stream[cur_stream].rate_den= denom;
} }
tmp = get_be64(bc); tmp = get_be64(bc);
if (tmp == INFO_STARTCODE){ if (tmp == INFO_STARTCODE){
get_packetheader(nut, bc, 8); get_packetheader(nut, bc, 8, 1);
for(;;){ for(;;){
int id= get_v(bc); int id= get_v(bc);
...@@ -943,7 +959,9 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -943,7 +959,9 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_str(bc, NULL, 0); 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 }else
url_fseek(bc, -8, SEEK_CUR); url_fseek(bc, -8, SEEK_CUR);
...@@ -986,9 +1004,9 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -986,9 +1004,9 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
if(flags & FLAG_FRAME_TYPE){ if(flags & FLAG_FRAME_TYPE){
reset(s); reset(s);
if(frame_type==2){ if(frame_type==2){
get_packetheader(nut, bc, 8+1); get_packetheader(nut, bc, 8+1, 0);
}else{ }else{
get_packetheader(nut, bc, 1); get_packetheader(nut, bc, 1, 0);
frame_type= 1; frame_type= 1;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment