search for undamaged headers

Originally committed as revision 2970 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Michael Niedermayer 2004-04-05 22:00:59 +00:00
parent 6b6242a205
commit 7c5934ede9

View File

@ -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;
int i, j;
nut->avf= s;
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;
}
@ -836,21 +863,22 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
return -1;
}
s->bit_rate = 0;
return 0;
}
nut->stream = av_malloc(sizeof(StreamContext)*nb_streams);
/* stream header */
for (cur_stream = 0; cur_stream < nb_streams; cur_stream++)
{
int class, nom, denom;
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;
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));
stream_id= get_v(bc);
if(stream_id >= nut->stream_count || s->streams[stream_id])
return -1;
st = av_new_stream(s, stream_id);
if (!st)
return AVERROR_NOMEM;
class = get_v(bc);
@ -877,11 +905,11 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_v(bc); /* language code */
nom = get_v(bc);
denom = get_v(bc);
nut->stream[cur_stream].msb_timestamp_shift = get_v(bc);
nut->stream[stream_id].msb_timestamp_shift = get_v(bc);
for(i=0; i<3; i++)
nut->stream[cur_stream].initial_pts_predictor[i]= get_v(bc);
nut->stream[stream_id].initial_pts_predictor[i]= get_v(bc);
for(i=0; i<2; i++)
nut->stream[cur_stream].initial_size_predictor[i]= get_v(bc);
nut->stream[stream_id].initial_size_predictor[i]= get_v(bc);
get_byte(bc); /* flags */
/* codec specific data headers */
@ -909,15 +937,18 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec.channels = get_v(bc);
}
if(check_checksum(bc)){
av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", cur_stream);
av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", stream_id);
return -1;
}
nut->stream[cur_stream].rate_num= nom;
nut->stream[cur_stream].rate_den= denom;
}
nut->stream[stream_id].rate_num= nom;
nut->stream[stream_id].rate_den= denom;
return 0;
}
static int decode_info_header(NUTContext *nut){
AVFormatContext *s= nut->avf;
ByteIOContext *bc = &s->pb;
tmp = get_be64(bc);
if (tmp == INFO_STARTCODE){
get_packetheader(nut, bc, 8, 1);
for(;;){
@ -961,9 +992,69 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
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);
}
}else
url_fseek(bc, -8, SEEK_CUR);
return 0;
}