comparison nut.c @ 419:51c25922a543 libavformat

search for undamaged headers
author michael
date Mon, 05 Apr 2004 22:00:59 +0000
parents 41da3366d341
children a35263593560
comparison
equal deleted inserted replaced
418:41da3366d341 419:51c25922a543
88 int64_t last_packet_start; 88 int64_t last_packet_start;
89 int written_packet_size; 89 int written_packet_size;
90 int64_t packet_size_pos; 90 int64_t packet_size_pos;
91 int64_t last_frame_start[3]; 91 int64_t last_frame_start[3];
92 FrameCode frame_code[256]; 92 FrameCode frame_code[256];
93 int stream_count;
93 StreamContext *stream; 94 StreamContext *stream;
94 } NUTContext; 95 } NUTContext;
95 96
96 static char *info_table[][2]={ 97 static char *info_table[][2]={
97 {NULL , NULL }, // end 98 {NULL , NULL }, // end
326 return i; 327 return i;
327 328
328 return 7; //not reached 329 return 7; //not reached
329 } 330 }
330 331
332 static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
333 uint64_t state=0;
334
335 if(pos >= 0)
336 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
337
338 while(bytes_left(bc)){
339 state= (state<<8) | get_byte(bc);
340 if((state>>56) != 'N')
341 continue;
342 switch(state){
343 case MAIN_STARTCODE:
344 case STREAM_STARTCODE:
345 case KEYFRAME_STARTCODE:
346 case INFO_STARTCODE:
347 case INDEX_STARTCODE:
348 return state;
349 }
350 }
351 return 0;
352 }
353
354 static int find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){
355 for(;;){
356 uint64_t startcode= find_any_startcode(bc, pos);
357 if(startcode == code)
358 return 0;
359 else if(startcode == 0)
360 return -1;
361 pos=-1;
362 }
363 }
364
331 #ifdef CONFIG_ENCODERS 365 #ifdef CONFIG_ENCODERS
332 static int put_v(ByteIOContext *bc, uint64_t val) 366 static int put_v(ByteIOContext *bc, uint64_t val)
333 { 367 {
334 int i; 368 int i;
335 // if (bytes_left(s)*8 < 9) 369 // if (bytes_left(s)*8 < 9)
761 return AVPROBE_SCORE_MAX; 795 return AVPROBE_SCORE_MAX;
762 } 796 }
763 return 0; 797 return 0;
764 } 798 }
765 799
766 static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap) 800 static int decode_main_header(NUTContext *nut){
767 { 801 AVFormatContext *s= nut->avf;
768 NUTContext *nut = s->priv_data;
769 ByteIOContext *bc = &s->pb; 802 ByteIOContext *bc = &s->pb;
770 uint64_t tmp; 803 uint64_t tmp;
771 int cur_stream, nb_streams, i, j; 804 int i, j;
772 805
773 nut->avf= s;
774
775 av_set_pts_info(s, 60, 1, AV_TIME_BASE);
776
777 /* main header */
778 tmp = get_be64(bc);
779 if (tmp != MAIN_STARTCODE)
780 av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp);
781 get_packetheader(nut, bc, 8, 1); 806 get_packetheader(nut, bc, 8, 1);
782 807
783 tmp = get_v(bc); 808 tmp = get_v(bc);
784 if (tmp != 1) 809 if (tmp != 1){
785 av_log(s, AV_LOG_ERROR, "bad version (%Ld)\n", tmp); 810 av_log(s, AV_LOG_ERROR, "bad version (%Ld)\n", tmp);
786 811 return -1;
787 nb_streams = get_v(bc); 812 }
813
814 nut->stream_count = get_v(bc);
788 get_v(bc); //checksum threshold 815 get_v(bc); //checksum threshold
789 816
790 for(i=0; i<256;){ 817 for(i=0; i<256;){
791 int tmp_flags = get_v(bc); 818 int tmp_flags = get_v(bc);
792 int tmp_stream= get_v(bc); 819 int tmp_stream= get_v(bc);
809 return -1; 836 return -1;
810 } 837 }
811 } 838 }
812 839
813 for(j=0; j<count; j++,i++){ 840 for(j=0; j<count; j++,i++){
814 if(tmp_stream > nb_streams + 1){ 841 if(tmp_stream > nut->stream_count + 1){
815 av_log(s, AV_LOG_ERROR, "illegal stream number\n"); 842 av_log(s, AV_LOG_ERROR, "illegal stream number\n");
816 return -1; 843 return -1;
817 } 844 }
818 845
819 nut->frame_code[i].flags = tmp_flags ; 846 nut->frame_code[i].flags = tmp_flags ;
828 } 855 }
829 if(nut->frame_code['N'].flags != 1){ 856 if(nut->frame_code['N'].flags != 1){
830 av_log(s, AV_LOG_ERROR, "illegal frame_code table\n"); 857 av_log(s, AV_LOG_ERROR, "illegal frame_code table\n");
831 return -1; 858 return -1;
832 } 859 }
833 860
834 if(check_checksum(bc)){ 861 if(check_checksum(bc)){
835 av_log(s, AV_LOG_ERROR, "Main header checksum missmatch\n"); 862 av_log(s, AV_LOG_ERROR, "Main header checksum missmatch\n");
836 return -1; 863 return -1;
837 } 864 }
865
866 return 0;
867 }
868
869 static int decode_stream_header(NUTContext *nut){
870 AVFormatContext *s= nut->avf;
871 ByteIOContext *bc = &s->pb;
872 int class, nom, denom, stream_id, i;
873 uint64_t tmp;
874 AVStream *st;
875
876 get_packetheader(nut, bc, 8, 1);
877 stream_id= get_v(bc);
878 if(stream_id >= nut->stream_count || s->streams[stream_id])
879 return -1;
880
881 st = av_new_stream(s, stream_id);
882 if (!st)
883 return AVERROR_NOMEM;
884 class = get_v(bc);
885 tmp = get_v(bc);
886 switch(class)
887 {
888 case 0:
889 st->codec.codec_type = CODEC_TYPE_VIDEO;
890 st->codec.codec_id = codec_get_bmp_id(tmp);
891 if (st->codec.codec_id == CODEC_ID_NONE)
892 av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
893 break;
894 case 32:
895 st->codec.codec_type = CODEC_TYPE_AUDIO;
896 st->codec.codec_id = codec_get_wav_id(tmp);
897 if (st->codec.codec_id == CODEC_ID_NONE)
898 av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
899 break;
900 default:
901 av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
902 return -1;
903 }
904 s->bit_rate += get_v(bc);
905 get_v(bc); /* language code */
906 nom = get_v(bc);
907 denom = get_v(bc);
908 nut->stream[stream_id].msb_timestamp_shift = get_v(bc);
909 for(i=0; i<3; i++)
910 nut->stream[stream_id].initial_pts_predictor[i]= get_v(bc);
911 for(i=0; i<2; i++)
912 nut->stream[stream_id].initial_size_predictor[i]= get_v(bc);
913 get_byte(bc); /* flags */
914
915 /* codec specific data headers */
916 while(get_v(bc) != 0){
917 st->codec.extradata_size= get_v(bc);
918 st->codec.extradata= av_mallocz(st->codec.extradata_size);
919 get_buffer(bc, st->codec.extradata, st->codec.extradata_size);
920 // url_fskip(bc, get_v(bc));
921 }
922
923 if (class == 0) /* VIDEO */
924 {
925 st->codec.width = get_v(bc);
926 st->codec.height = get_v(bc);
927 st->codec.sample_aspect_ratio.num= get_v(bc);
928 st->codec.sample_aspect_ratio.den= get_v(bc);
929 get_v(bc); /* csp type */
930
931 st->codec.frame_rate = nom;
932 st->codec.frame_rate_base = denom;
933 }
934 if (class == 32) /* AUDIO */
935 {
936 st->codec.sample_rate = (get_v(bc) * nom) / denom;
937 st->codec.channels = get_v(bc);
938 }
939 if(check_checksum(bc)){
940 av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", stream_id);
941 return -1;
942 }
943 nut->stream[stream_id].rate_num= nom;
944 nut->stream[stream_id].rate_den= denom;
945 return 0;
946 }
947
948 static int decode_info_header(NUTContext *nut){
949 AVFormatContext *s= nut->avf;
950 ByteIOContext *bc = &s->pb;
951
952 get_packetheader(nut, bc, 8, 1);
953
954 for(;;){
955 int id= get_v(bc);
956 char *name, *type, custom_name[256], custom_type[256];
957
958 if(!id)
959 break;
960 else if(id >= sizeof(info_table)/sizeof(info_table[0])){
961 av_log(s, AV_LOG_ERROR, "info id is too large %d %d\n", id, sizeof(info_table)/sizeof(info_table[0]));
962 return -1;
963 }
964
965 type= info_table[id][1];
966 name= info_table[id][0];
967 //av_log(s, AV_LOG_DEBUG, "%d %s %s\n", id, type, name);
968
969 if(!type){
970 get_str(bc, custom_type, sizeof(custom_type));
971 type= custom_type;
972 }
973 if(!name){
974 get_str(bc, custom_name, sizeof(custom_name));
975 name= custom_name;
976 }
977
978 if(!strcmp(type, "v")){
979 int value= get_v(bc);
980 }else{
981 if(!strcmp(name, "Author"))
982 get_str(bc, s->author, sizeof(s->author));
983 else if(!strcmp(name, "Title"))
984 get_str(bc, s->title, sizeof(s->title));
985 else if(!strcmp(name, "Copyright"))
986 get_str(bc, s->copyright, sizeof(s->copyright));
987 else if(!strcmp(name, "Description"))
988 get_str(bc, s->comment, sizeof(s->comment));
989 else
990 get_str(bc, NULL, 0);
991 }
992 }
993 if(check_checksum(bc)){
994 av_log(s, AV_LOG_ERROR, "Info header checksum missmatch\n");
995 return -1;
996 }
997 return 0;
998 }
999
1000 static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
1001 {
1002 NUTContext *nut = s->priv_data;
1003 ByteIOContext *bc = &s->pb;
1004 int64_t pos;
1005 int inited_stream_count;
1006
1007 nut->avf= s;
1008
1009 av_set_pts_info(s, 60, 1, AV_TIME_BASE);
1010
1011 /* main header */
1012 pos=0;
1013 for(;;){
1014 if (find_startcode(bc, MAIN_STARTCODE, pos)<0){
1015 av_log(s, AV_LOG_ERROR, "no main startcode found\n");
1016 return -1;
1017 }
1018 pos= url_ftell(bc);
1019 if(decode_main_header(nut) >= 0)
1020 break;
1021 }
1022
838 1023
839 s->bit_rate = 0; 1024 s->bit_rate = 0;
840 1025
841 nut->stream = av_malloc(sizeof(StreamContext)*nb_streams); 1026 nut->stream = av_malloc(sizeof(StreamContext)*nut->stream_count);
842 1027
843 /* stream header */ 1028 /* stream headers */
844 for (cur_stream = 0; cur_stream < nb_streams; cur_stream++) 1029 pos=0;
845 { 1030 for(inited_stream_count=0; inited_stream_count < nut->stream_count;){
846 int class, nom, denom; 1031 if (find_startcode(bc, STREAM_STARTCODE, pos)<0){
847 AVStream *st; 1032 av_log(s, AV_LOG_ERROR, "not all stream headers found\n");
848
849 tmp = get_be64(bc);
850 if (tmp != STREAM_STARTCODE)
851 av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp);
852 get_packetheader(nut, bc, 8, 1);
853 st = av_new_stream(s, get_v(bc));
854 if (!st)
855 return AVERROR_NOMEM;
856 class = get_v(bc);
857 tmp = get_v(bc);
858 switch(class)
859 {
860 case 0:
861 st->codec.codec_type = CODEC_TYPE_VIDEO;
862 st->codec.codec_id = codec_get_bmp_id(tmp);
863 if (st->codec.codec_id == CODEC_ID_NONE)
864 av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
865 break;
866 case 32:
867 st->codec.codec_type = CODEC_TYPE_AUDIO;
868 st->codec.codec_id = codec_get_wav_id(tmp);
869 if (st->codec.codec_id == CODEC_ID_NONE)
870 av_log(s, AV_LOG_ERROR, "Unknown codec?!\n");
871 break;
872 default:
873 av_log(s, AV_LOG_ERROR, "Unknown stream class (%d)\n", class);
874 return -1;
875 }
876 s->bit_rate += get_v(bc);
877 get_v(bc); /* language code */
878 nom = get_v(bc);
879 denom = get_v(bc);
880 nut->stream[cur_stream].msb_timestamp_shift = get_v(bc);
881 for(i=0; i<3; i++)
882 nut->stream[cur_stream].initial_pts_predictor[i]= get_v(bc);
883 for(i=0; i<2; i++)
884 nut->stream[cur_stream].initial_size_predictor[i]= get_v(bc);
885 get_byte(bc); /* flags */
886
887 /* codec specific data headers */
888 while(get_v(bc) != 0){
889 st->codec.extradata_size= get_v(bc);
890 st->codec.extradata= av_mallocz(st->codec.extradata_size);
891 get_buffer(bc, st->codec.extradata, st->codec.extradata_size);
892 // url_fskip(bc, get_v(bc));
893 }
894
895 if (class == 0) /* VIDEO */
896 {
897 st->codec.width = get_v(bc);
898 st->codec.height = get_v(bc);
899 st->codec.sample_aspect_ratio.num= get_v(bc);
900 st->codec.sample_aspect_ratio.den= get_v(bc);
901 get_v(bc); /* csp type */
902
903 st->codec.frame_rate = nom;
904 st->codec.frame_rate_base = denom;
905 }
906 if (class == 32) /* AUDIO */
907 {
908 st->codec.sample_rate = (get_v(bc) * nom) / denom;
909 st->codec.channels = get_v(bc);
910 }
911 if(check_checksum(bc)){
912 av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", cur_stream);
913 return -1; 1033 return -1;
914 } 1034 }
915 nut->stream[cur_stream].rate_num= nom; 1035 pos= url_ftell(bc);
916 nut->stream[cur_stream].rate_den= denom; 1036 if(decode_stream_header(nut) >= 0)
917 } 1037 inited_stream_count++;
918 1038 }
919 tmp = get_be64(bc); 1039
920 if (tmp == INFO_STARTCODE){ 1040 /* info headers */
921 get_packetheader(nut, bc, 8, 1); 1041 pos=0;
922 1042 for(;;){
923 for(;;){ 1043 uint64_t startcode= find_any_startcode(bc, pos);
924 int id= get_v(bc); 1044 pos= url_ftell(bc);
925 char *name, *type, custom_name[256], custom_type[256]; 1045
926 1046 if(startcode==0){
927 if(!id) 1047 av_log(s, AV_LOG_ERROR, "EOF before video frames\n");
928 break; 1048 return -1;
929 else if(id >= sizeof(info_table)/sizeof(info_table[0])){ 1049 }else if(startcode == KEYFRAME_STARTCODE){
930 av_log(s, AV_LOG_ERROR, "info id is too large %d %d\n", id, sizeof(info_table)/sizeof(info_table[0])); 1050 url_fseek(bc, -8, SEEK_CUR); //FIXME
931 return -1; 1051 break;
932 } 1052 }else if(startcode != INFO_STARTCODE){
933 1053 continue;
934 type= info_table[id][1]; 1054 }
935 name= info_table[id][0]; 1055
936 //av_log(s, AV_LOG_DEBUG, "%d %s %s\n", id, type, name); 1056 decode_info_header(nut);
937 1057 }
938 if(!type){ 1058
939 get_str(bc, custom_type, sizeof(custom_type));
940 type= custom_type;
941 }
942 if(!name){
943 get_str(bc, custom_name, sizeof(custom_name));
944 name= custom_name;
945 }
946
947 if(!strcmp(type, "v")){
948 int value= get_v(bc);
949 }else{
950 if(!strcmp(name, "Author"))
951 get_str(bc, s->author, sizeof(s->author));
952 else if(!strcmp(name, "Title"))
953 get_str(bc, s->title, sizeof(s->title));
954 else if(!strcmp(name, "Copyright"))
955 get_str(bc, s->copyright, sizeof(s->copyright));
956 else if(!strcmp(name, "Description"))
957 get_str(bc, s->comment, sizeof(s->comment));
958 else
959 get_str(bc, NULL, 0);
960 }
961 }
962 if(check_checksum(bc)){
963 av_log(s, AV_LOG_ERROR, "Info header checksum missmatch\n");
964 }
965 }else
966 url_fseek(bc, -8, SEEK_CUR);
967
968 return 0; 1059 return 0;
969 } 1060 }
970 1061
971 static int nut_read_packet(AVFormatContext *s, AVPacket *pkt) 1062 static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
972 { 1063 {