aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2004-04-05 22:00:59 +0000
committerMichael Niedermayer <michaelni@gmx.at>2004-04-05 22:00:59 +0000
commit7c5934ede9f352408c34b638cfccf2d4b3cd8972 (patch)
tree6ec2fb605b42589bb25e078d42d767133f809616
parent6b6242a2050eabdacd6fd4a58c49d29c7b5f2038 (diff)
downloadffmpeg-7c5934ede9f352408c34b638cfccf2d4b3cd8972.tar.gz
search for undamaged headers
Originally committed as revision 2970 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavformat/nut.c359
1 files changed, 225 insertions, 134 deletions
diff --git a/libavformat/nut.c b/libavformat/nut.c
index efe4debd9b..ffb7866081 100644
--- a/libavformat/nut.c
+++ b/libavformat/nut.c
@@ -90,6 +90,7 @@ typedef struct {
int64_t packet_size_pos;
int64_t last_frame_start[3];
FrameCode frame_code[256];
+ int stream_count;
StreamContext *stream;
} NUTContext;
@@ -328,6 +329,39 @@ static int get_length(uint64_t val){
return 7; //not reached
}
+static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
+ uint64_t state=0;
+
+ if(pos >= 0)
+ url_fseek(bc, pos, SEEK_SET); //note, this may fail if the stream isnt seekable, but that shouldnt matter, as in this case we simply start where we are currently
+
+ while(bytes_left(bc)){
+ state= (state<<8) | get_byte(bc);
+ if((state>>56) != 'N')
+ continue;
+ switch(state){
+ case MAIN_STARTCODE:
+ case STREAM_STARTCODE:
+ case KEYFRAME_STARTCODE:
+ case INFO_STARTCODE:
+ case INDEX_STARTCODE:
+ return state;
+ }
+ }
+ return 0;
+}
+
+static int find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){
+ for(;;){
+ uint64_t startcode= find_any_startcode(bc, pos);
+ if(startcode == code)
+ return 0;
+ else if(startcode == 0)
+ return -1;
+ pos=-1;
+ }
+}
+
#ifdef CONFIG_ENCODERS
static int put_v(ByteIOContext *bc, uint64_t val)
{
@@ -763,28 +797,21 @@ static int nut_probe(AVProbeData *p)
return 0;
}
-static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
-{
- NUTContext *nut = s->priv_data;
+static int decode_main_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
ByteIOContext *bc = &s->pb;
uint64_t tmp;
- int cur_stream, nb_streams, i, j;
-
- nut->avf= s;
+ int i, j;
- av_set_pts_info(s, 60, 1, AV_TIME_BASE);
-
- /* main header */
- 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, 1);
-
+
tmp = get_v(bc);
- if (tmp != 1)
+ if (tmp != 1){
av_log(s, AV_LOG_ERROR, "bad version (%Ld)\n", tmp);
+ return -1;
+ }
- nb_streams = get_v(bc);
+ nut->stream_count = get_v(bc);
get_v(bc); //checksum threshold
for(i=0; i<256;){
@@ -811,7 +838,7 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
for(j=0; j<count; j++,i++){
- if(tmp_stream > nb_streams + 1){
+ if(tmp_stream > nut->stream_count + 1){
av_log(s, AV_LOG_ERROR, "illegal stream number\n");
return -1;
}
@@ -830,141 +857,205 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
av_log(s, AV_LOG_ERROR, "illegal frame_code table\n");
return -1;
}
-
+
if(check_checksum(bc)){
av_log(s, AV_LOG_ERROR, "Main header checksum missmatch\n");
return -1;
}
-
- s->bit_rate = 0;
- nut->stream = av_malloc(sizeof(StreamContext)*nb_streams);
+ return 0;
+}
+
+static int decode_stream_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+ int class, nom, denom, stream_id, i;
+ uint64_t tmp;
+ AVStream *st;
+
+ get_packetheader(nut, bc, 8, 1);
+ stream_id= get_v(bc);
+ if(stream_id >= nut->stream_count || s->streams[stream_id])
+ return -1;
- /* stream header */
- for (cur_stream = 0; cur_stream < nb_streams; cur_stream++)
+ st = av_new_stream(s, stream_id);
+ if (!st)
+ return AVERROR_NOMEM;
+ class = get_v(bc);
+ tmp = get_v(bc);
+ switch(class)
{
- int class, nom, denom;
- AVStream *st;
-
- 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, 1);
- st = av_new_stream(s, get_v(bc));
- if (!st)
- return AVERROR_NOMEM;
- class = get_v(bc);
- tmp = get_v(bc);
- switch(class)
- {
- case 0:
- st->codec.codec_type = CODEC_TYPE_VIDEO;
- st->codec.codec_id = codec_get_bmp_id(tmp);
- if (st->codec.codec_id == CODEC_ID_NONE)
- av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
- break;
- case 32:
- st->codec.codec_type = CODEC_TYPE_AUDIO;
- st->codec.codec_id = codec_get_wav_id(tmp);
- if (st->codec.codec_id == CODEC_ID_NONE)
- av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
- break;
- default:
- av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
- return -1;
- }
- s->bit_rate += get_v(bc);
- get_v(bc); /* language code */
- nom = get_v(bc);
- denom = get_v(bc);
- nut->stream[cur_stream].msb_timestamp_shift = get_v(bc);
- for(i=0; i<3; i++)
- nut->stream[cur_stream].initial_pts_predictor[i]= get_v(bc);
- for(i=0; i<2; i++)
- nut->stream[cur_stream].initial_size_predictor[i]= get_v(bc);
- get_byte(bc); /* flags */
-
- /* codec specific data headers */
- while(get_v(bc) != 0){
- st->codec.extradata_size= get_v(bc);
- st->codec.extradata= av_mallocz(st->codec.extradata_size);
- get_buffer(bc, st->codec.extradata, st->codec.extradata_size);
-// url_fskip(bc, get_v(bc));
- }
-
- if (class == 0) /* VIDEO */
- {
- st->codec.width = get_v(bc);
- st->codec.height = get_v(bc);
- st->codec.sample_aspect_ratio.num= get_v(bc);
- st->codec.sample_aspect_ratio.den= get_v(bc);
- get_v(bc); /* csp type */
-
- st->codec.frame_rate = nom;
- st->codec.frame_rate_base = denom;
- }
- if (class == 32) /* AUDIO */
- {
- st->codec.sample_rate = (get_v(bc) * nom) / denom;
- st->codec.channels = get_v(bc);
- }
- if(check_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", cur_stream);
+ case 0:
+ st->codec.codec_type = CODEC_TYPE_VIDEO;
+ st->codec.codec_id = codec_get_bmp_id(tmp);
+ if (st->codec.codec_id == CODEC_ID_NONE)
+ av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
+ break;
+ case 32:
+ st->codec.codec_type = CODEC_TYPE_AUDIO;
+ st->codec.codec_id = codec_get_wav_id(tmp);
+ if (st->codec.codec_id == CODEC_ID_NONE)
+ av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
+ break;
+ default:
+ av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
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, 1);
+ s->bit_rate += get_v(bc);
+ get_v(bc); /* language code */
+ nom = get_v(bc);
+ denom = get_v(bc);
+ nut->stream[stream_id].msb_timestamp_shift = get_v(bc);
+ for(i=0; i<3; i++)
+ nut->stream[stream_id].initial_pts_predictor[i]= get_v(bc);
+ for(i=0; i<2; i++)
+ nut->stream[stream_id].initial_size_predictor[i]= get_v(bc);
+ get_byte(bc); /* flags */
+
+ /* codec specific data headers */
+ while(get_v(bc) != 0){
+ st->codec.extradata_size= get_v(bc);
+ st->codec.extradata= av_mallocz(st->codec.extradata_size);
+ get_buffer(bc, st->codec.extradata, st->codec.extradata_size);
+// url_fskip(bc, get_v(bc));
+ }
- for(;;){
- int id= get_v(bc);
- char *name, *type, custom_name[256], custom_type[256];
+ if (class == 0) /* VIDEO */
+ {
+ st->codec.width = get_v(bc);
+ st->codec.height = get_v(bc);
+ st->codec.sample_aspect_ratio.num= get_v(bc);
+ st->codec.sample_aspect_ratio.den= get_v(bc);
+ get_v(bc); /* csp type */
+
+ st->codec.frame_rate = nom;
+ st->codec.frame_rate_base = denom;
+ }
+ if (class == 32) /* AUDIO */
+ {
+ st->codec.sample_rate = (get_v(bc) * nom) / denom;
+ st->codec.channels = get_v(bc);
+ }
+ if(check_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", stream_id);
+ return -1;
+ }
+ nut->stream[stream_id].rate_num= nom;
+ nut->stream[stream_id].rate_den= denom;
+ return 0;
+}
- if(!id)
- break;
- else if(id >= sizeof(info_table)/sizeof(info_table[0])){
- av_log(s, AV_LOG_ERROR, "info id is too large %d %d\n", id, sizeof(info_table)/sizeof(info_table[0]));
- return -1;
- }
+static int decode_info_header(NUTContext *nut){
+ AVFormatContext *s= nut->avf;
+ ByteIOContext *bc = &s->pb;
+
+ get_packetheader(nut, bc, 8, 1);
+
+ for(;;){
+ int id= get_v(bc);
+ char *name, *type, custom_name[256], custom_type[256];
+
+ if(!id)
+ break;
+ else if(id >= sizeof(info_table)/sizeof(info_table[0])){
+ av_log(s, AV_LOG_ERROR, "info id is too large %d %d\n", id, sizeof(info_table)/sizeof(info_table[0]));
+ return -1;
+ }
- type= info_table[id][1];
- name= info_table[id][0];
+ type= info_table[id][1];
+ name= info_table[id][0];
//av_log(s, AV_LOG_DEBUG, "%d %s %s\n", id, type, name);
- if(!type){
- get_str(bc, custom_type, sizeof(custom_type));
- type= custom_type;
- }
- if(!name){
- get_str(bc, custom_name, sizeof(custom_name));
- name= custom_name;
- }
-
- if(!strcmp(type, "v")){
- int value= get_v(bc);
- }else{
- if(!strcmp(name, "Author"))
- get_str(bc, s->author, sizeof(s->author));
- else if(!strcmp(name, "Title"))
- get_str(bc, s->title, sizeof(s->title));
- else if(!strcmp(name, "Copyright"))
- get_str(bc, s->copyright, sizeof(s->copyright));
- else if(!strcmp(name, "Description"))
- get_str(bc, s->comment, sizeof(s->comment));
- else
- get_str(bc, NULL, 0);
- }
+ if(!type){
+ get_str(bc, custom_type, sizeof(custom_type));
+ type= custom_type;
+ }
+ if(!name){
+ get_str(bc, custom_name, sizeof(custom_name));
+ name= custom_name;
}
- if(check_checksum(bc)){
- av_log(s, AV_LOG_ERROR, "Info header checksum missmatch\n");
+
+ if(!strcmp(type, "v")){
+ int value= get_v(bc);
+ }else{
+ if(!strcmp(name, "Author"))
+ get_str(bc, s->author, sizeof(s->author));
+ else if(!strcmp(name, "Title"))
+ get_str(bc, s->title, sizeof(s->title));
+ else if(!strcmp(name, "Copyright"))
+ get_str(bc, s->copyright, sizeof(s->copyright));
+ else if(!strcmp(name, "Description"))
+ get_str(bc, s->comment, sizeof(s->comment));
+ else
+ get_str(bc, NULL, 0);
}
- }else
- url_fseek(bc, -8, SEEK_CUR);
+ }
+ if(check_checksum(bc)){
+ av_log(s, AV_LOG_ERROR, "Info header checksum missmatch\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+ NUTContext *nut = s->priv_data;
+ ByteIOContext *bc = &s->pb;
+ int64_t pos;
+ int inited_stream_count;
+
+ nut->avf= s;
+ av_set_pts_info(s, 60, 1, AV_TIME_BASE);
+
+ /* main header */
+ pos=0;
+ for(;;){
+ if (find_startcode(bc, MAIN_STARTCODE, pos)<0){
+ av_log(s, AV_LOG_ERROR, "no main startcode found\n");
+ return -1;
+ }
+ pos= url_ftell(bc);
+ if(decode_main_header(nut) >= 0)
+ break;
+ }
+
+
+ s->bit_rate = 0;
+
+ nut->stream = av_malloc(sizeof(StreamContext)*nut->stream_count);
+
+ /* stream headers */
+ pos=0;
+ for(inited_stream_count=0; inited_stream_count < nut->stream_count;){
+ if (find_startcode(bc, STREAM_STARTCODE, pos)<0){
+ av_log(s, AV_LOG_ERROR, "not all stream headers found\n");
+ return -1;
+ }
+ pos= url_ftell(bc);
+ if(decode_stream_header(nut) >= 0)
+ inited_stream_count++;
+ }
+
+ /* info headers */
+ pos=0;
+ for(;;){
+ uint64_t startcode= find_any_startcode(bc, pos);
+ pos= url_ftell(bc);
+
+ if(startcode==0){
+ av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
+ return -1;
+ }else if(startcode == KEYFRAME_STARTCODE){
+ url_fseek(bc, -8, SEEK_CUR); //FIXME
+ break;
+ }else if(startcode != INFO_STARTCODE){
+ continue;
+ }
+
+ decode_info_header(nut);
+ }
+
return 0;
}