diff --git a/TOOLS/avi-fix.c b/TOOLS/avi-fix.c new file mode 100644 index 0000000000..45bb4c8fa8 --- /dev/null +++ b/TOOLS/avi-fix.c @@ -0,0 +1,136 @@ +// avi-fix v0.1 (C) A'rpi, license GPL +// simple tool to fix chunk sizes in a RIFF AVI file +// it doesn't check/fix index, use mencoder -forceidx -oac copy -ovc copy to fix index! + +#include +#include +//#include + +#define FCC(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d)) + +static inline xx(unsigned char c){ + if(c>=32 && c<128) return c; + return '?'; +} + +static inline unsigned int getid(FILE* f){ + unsigned int id; + id=fgetc(f); + id=(id<<8)|fgetc(f); + id=(id<<8)|fgetc(f); + id=(id<<8)|fgetc(f); + return id; +} + +int main(int argc,char* argv[]){ +//FILE* f=fopen("edgar.avi","rb"); // readonly (report errors) +//FILE* f=fopen("edgar.avi","rb+"); // fix mode (fix chunk sizes) +unsigned int lastgood=0; +unsigned int fixat=0; +unsigned int offset=0; +int fix_flag=0; +FILE* f; + +if(argc<=1){ + printf("Usage: %s [-fix] badfile.avi\n",argv[0]); + exit(1); +} + +if(!strcmp(argv[1],"-fix")){ + fix_flag=1; + f=fopen(argv[argc-1],"rb+"); +} else + f=fopen(argv[argc-1],"rb"); + +if(!f){ + perror("error"); + printf("couldnt open '%s'\n",argv[argc-1]); + exit(2); +} + +while(1){ + unsigned int id,len; +again: + id=fgetc(f); + id=(id<<8)|fgetc(f); + id=(id<<8)|fgetc(f); +faszom: + if(feof(f)) break; +// if(!lastgood && feof(f)) break; + id=(id<<8)|fgetc(f); +// lastgood=ftell(f); + printf("%08X: %c%c%c%c\n",(int)ftell(f)-4,xx(id>>24),xx(id>>16),xx(id>>8),xx(id)); + switch(id){ + case FCC('R','I','F','F'): + fread(&len,4,1,f); // filesize + id=getid(f); // AVI + printf("RIFF header, filesize=0x%X format=%c%c%c%c\n",len,xx(id>>24),xx(id>>16),xx(id>>8),xx(id)); + break; + case FCC('L','I','S','T'): + fread(&len,4,1,f); // size + id=getid(f); // AVI + printf("LIST size=0x%X format=%c%c%c%c\n",len,xx(id>>24),xx(id>>16),xx(id>>8),xx(id)); + //case FCC('h','d','r','l'): + //case FCC('s','t','r','l'): + //case FCC('o','d','m','l'): + //case FCC('m','o','v','i'): + break; + // legal chunk IDs: + case FCC('a','v','i','h'): // avi header + case FCC('s','t','r','h'): // stream header + case FCC('s','t','r','f'): // stream format + case FCC('J','U','N','K'): // official shit + // index: + case FCC('i','d','x','1'): // main index?? + case FCC('d','m','l','h'): // opendml header + case FCC('i','n','d','x'): // opendml main index?? + case FCC('i','x','0','0'): // opendml sub index?? + case FCC('i','x','0','1'): // opendml sub index?? + // data: + case FCC('0','1','w','b'): // audio track #1 + case FCC('0','2','w','b'): // audio track #2 + case FCC('0','3','w','b'): // audio track #3 + case FCC('0','0','d','b'): // uncompressed video + case FCC('0','0','d','c'): // compressed video + case FCC('0','0','_','_'): // A-V interleaved (type2 DV file) + // info: + case FCC('I','S','F','T'): // INFO: software + case FCC('I','S','R','C'): // INFO: source + case FCC('I','N','A','M'): // INFO: name + case FCC('I','S','B','J'): // INFO: subject + case FCC('I','A','R','T'): // INFO: artist + case FCC('I','C','O','P'): // INFO: copyright + case FCC('I','C','M','T'): // INFO: comment + lastgood=ftell(f); + if(fixat && fix_flag){ + // fix last chunk's size field: + fseek(f,fixat,SEEK_SET); + len=lastgood-fixat-8; + printf("Correct len to 0x%X\n",len); + fwrite(&len,4,1,f); + fseek(f,lastgood,SEEK_SET); + fixat=0; + } + fread(&len,4,1,f); // size + printf("ID ok, chunk len=0x%X\n",len); + len+=len&1; // align at 2 + fseek(f,len,SEEK_CUR); // skip data + break; + default: + if(!lastgood){ + ++offset; + printf("invalid ID, trying %d byte offset\n",offset); + goto faszom; // try again @ next post + } + printf("invalid ID, parsing next chunk's data at 0x%X\n",lastgood); + fseek(f,lastgood,SEEK_SET); + fixat=lastgood; + lastgood=0; + goto again; + } + offset=0; +} + + +} +