#include "h/aviread.h" #include "h/ogm_hack.h" int AviSeek( FILE* file, FOURCC ID ) { //seek a avi file till found a requested chunk. return a Size of chunk //or zero, if no requsted chunk found. struct{ FOURCC ID; DWORD Size; } chunk; /*reference view of chunk*/ if( !fread( &chunk, sizeof( chunk ), 1,file ) ) return 0; while( chunk.ID!= ID ) { fseek( file, chunk.Size, SEEK_CUR ); if( !fread( &chunk, sizeof( chunk ), 1, file) ) return 0; } return chunk.Size; } int ReadOGM(FILE *file, MainAVIHeader *avih, mem_chunk **str_data){ OgmHackedHeader ogm; fseek(file, OGM_HACK_HEADER_OFFSET, SEEK_SET); if(!fread(&ogm,sizeof(ogm),1,file)) return -41; *str_data=malloc(sizeof(mem_chunk)); if(!*str_data) return -42; (*str_data)->Next=NULL; (*str_data)->Data_h=malloc(sizeof(AVIStreamHeader)); (*str_data)->DataSize_h=sizeof(AVIStreamHeader); (*str_data)->Data_f.v=malloc(sizeof(BITMAPINFOHEADER)); (*str_data)->DataSize_f=sizeof(BITMAPINFOHEADER); avih->dwMicroSecPerFrame=ogm.SpF/10; //fps avih->dwMaxBytesPerSec=0; avih->dwFlags=0; // avih->dwTotalFrames !!! avih->dwInitialFrames=0; avih->dwStreams=1; avih->dwSuggestedBufferSize=0; avih->dwWidth=ogm.width; avih->dwHeight=ogm.height; avih->dwScale=0; avih->dwRate=0; avih->dwStart=0; avih->dwLength=0; (*str_data)->number=1; (*str_data)->Data_h->fccType=*(int*)"vids"; (*str_data)->Data_h->fccHandler=ogm.Codec; (*str_data)->Data_f.v->biWidth=ogm.width; (*str_data)->Data_f.v->biHeight=ogm.height; (*str_data)->Data_f.v->biBitCount=ogm.bps; (*str_data)->Data_f.v->biCompression=ogm.Codec; flags.disable.streams=1; flags.disable.index=1; flags.disable.info=1; return 0; } int ReadAVI( FILE *file, MainAVIHeader *avihdr, mem_chunk **str_data ){ DWORD riffType; DWORD Size; unsigned int StreamNumber=0; int SizeCount; DWORD signature; mem_chunk* current = NULL; mem_chunk* temp; int error = 0; //error code if(flags.ogm) return ReadOGM(file, avihdr, str_data); if (!flags.direct.header){//use normal ("right") pasing fseek(file, 0, SEEK_SET );//rewind if( !AviSeek( file, SIGN_RIFF ) ) return -2; if( !fread( &riffType, 1, sizeof( riffType ), file) ) return -1; if( riffType != SIGN_AVI_ ) return 2;//error: riff, but not AVI (e.g. WAV,RMI) while( riffType != SIGN_HDRL ) { //if not a 'hrdl' type, skip all LIST chunk. if( !AviSeek( file, SIGN_LIST ) ) return -2; if( !fread( &riffType, sizeof( riffType ), 1, file) ) return -1; } if( !fread( &riffType, sizeof( riffType ), 1, file) ) return -1; if( riffType != SIGN_AVIH ) return -3; if( !fread( &Size, sizeof( Size ), 1, file) ) return -1; if( Size != sizeof( MainAVIHeader ) ) error = -4;//size of avi header does not match. if( !fread( avihdr, Size, 1, file ) ) return -1; } else {//direct header reading (wrong, but faster then above) fseek( file, 0x20, SEEK_SET ); if( !fread( avihdr, sizeof( MainAVIHeader), 1, file) ) return -1; }; *str_data = NULL; while(1){ do{ SizeCount = AviSeek( file, SIGN_LIST ); if( !SizeCount ) return -21; if( !fread( &signature, sizeof( signature ), 1, file ) )return -22; if(signature==SIGN_movi) return StreamNumber; //return number of found streams }while( signature != SIGN_STRL ); StreamNumber++; temp = (mem_chunk*)malloc( sizeof( mem_chunk ) ); if( !temp ) return -23; temp->Next=NULL; if( current ) current->Next = temp; else current = temp; if( !*str_data ) *str_data = current; if( !fread( &signature, 1,sizeof( signature ), file ) ) return -24; if( !fread( &Size, 1,sizeof( Size ), file ) ) return -25; if( signature == SIGN_STRH ) { if( !(temp->Data_h = (void*)malloc( Size ) ) ) return -26; if( !fread( temp->Data_h, 1, Size, file ) ) return -27; temp->DataSize_h = Size; SizeCount = SizeCount - Size - 12; if( SizeCount > 0 ) { if( !fread( &signature , 1, sizeof( signature ), file ) ) return -28; if( !fread( &Size, 1, sizeof( Size ), file ) ) return -29; } } if( signature == SIGN_STRF ) { if( !(temp->Data_f.v = (void*) malloc( Size ) ) ) return -30; if( !fread( temp->Data_f.v, 1, Size, file ) ) return -31; temp->DataSize_f = Size; SizeCount = SizeCount - Size - 8; if( SizeCount > 0 ) { if( !fread( &signature , 1, sizeof( signature ), file ) ) return -32; if( !fread( &Size, 1, sizeof( Size ), file ) ) return -33; SizeCount = SizeCount - 8; } } if(signature == SIGN_STRD) { if( !(temp->Data_d = (void*)malloc( Size ) ) ) return -34; if( !fread(temp->Data_d, 1, Size, file ) ) return -35; temp->DataSize_d = Size; } if( SizeCount > 0 ) fseek( file, SizeCount, SEEK_CUR ); temp->number=StreamNumber; current=temp; } return 0; } int ReadAVIinfo( FILE *file, char *info[24] ) { //reading AVI LIST-INFO data to the info[] //TODO: !!! parse more then one LIST[INFO]. //return value: 0 if OK, <0 if error int ChunkSize, size; int signature; int count; fseek(file,0,SEEK_SET);//rewind (c) Cardigans ChunkSize=AviSeek(file,SIGN_RIFF); if(!ChunkSize) return -1;//no RIFF chunk -_- if( !fread( &signature, sizeof( signature ), 1, file ) )return -1; if (signature!=SIGN_AVI_) return -1; do{ ChunkSize=AviSeek(file,SIGN_LIST); if(!ChunkSize) return -1;//no LIST ChunkSize=ChunkSize-4; if( !fread( &signature, sizeof( signature ), 1, file ) )return -1; if (signature!=SIGN_INFO) {fseek(file,ChunkSize,SEEK_CUR);} }while(signature!=SIGN_INFO); do{ if( !fread( &signature, sizeof( signature ), 1, file ) )return -1; for(count=0;count<23;count++) {//trowgh all INFO tags. if(!chk(info_names[count],signature)) { if( !fread( &size, sizeof( size ), 1, file ) )return -1; size++;//some workaround (size is a size of string whitout ending zero info[count]=malloc(size); if(!info[count]) return -1; if( !fread( info[count], size, 1, file ) )return -1; } } ChunkSize=ChunkSize-size-8; } while(ChunkSize>8); return 0; } int ReadIDX1(FILE *file, idx1 **index) { //reading old (idx1) index to memory from "file" //return value: size of the index //or -1 if error. 0 - if no index found int signature, size; fseek(file,0,SEEK_SET); size=AviSeek(file,SIGN_RIFF); if(!size) return -1;//no RIFF chunk -_- if( !fread( &signature, sizeof( signature ), 1, file ) )return -1; if (signature!=SIGN_AVI_) return -1; if(!(size=AviSeek(file,SIGN_IDX1))) return -1; //no LIST *index=malloc(size); if(!*index) return -2; if( !fread( *index, size, 1, file) ) return -1; return size; } void ParseIDX1(idx1 index[], unsigned int IndexSize, unsigned int dwStreams, idxStat *StreamStat[], idxStat *Global, idxStat *Audio, idxStat *Video) { unsigned int elements=IndexSize/sizeof(idx1); unsigned int counter; unsigned int nc;//stream number unsigned int tc;//type of the stream unsigned int key; //flag - keyframe or not unsigned int flag; *StreamStat=calloc(sizeof(idxStat) , dwStreams); //create the array for stat fill with zero fill((char*)Global, '\x0',sizeof(idxStat)); fill((char*)Audio, '\x0',sizeof(idxStat)); fill((char*)Video, '\x0',sizeof(idxStat)); for(counter=0;counter>16;//type of stream - 'd' - video, 'w' - audio nc=((index[counter].dwChunkid&0x000000FF)-'0')*10; nc+=((index[counter].dwChunkid&0x0000FF00)>>8)-'0';//get a stream number if (nc>dwStreams ) continue;//do not process the stream with wrong number if(index[counter].dwFlags & AVIIF_LIST) continue; //skip a REC chunk index entry key=!!(index[counter].dwFlags &AVIIF_KEYFRAME);// 0 or 1 , 0 - if normal, 1 - if K/F flag=1; while(flag){ (*StreamStat)[nc].Number[key]++; (*StreamStat)[nc].TotalSize[key]+=index[counter].dwSize; if(index[counter].dwSize>(*StreamStat)[nc].MaxSize[key]) (*StreamStat)[nc].MaxSize[key]=index[counter].dwSize; if(index[counter].dwSize<(*StreamStat)[nc].MinSize[key] || (*StreamStat)[nc].MinSize[key]==0 ) (*StreamStat)[nc].MinSize[key]=index[counter].dwSize; //Global Data Global->Number[key]++; Global->TotalSize[key]+=index[counter].dwSize; if(index[counter].dwSize>Global->MaxSize[key]) Global->MaxSize[key]=index[counter].dwSize; if(index[counter].dwSizeMinSize[key] || Global->MinSize[key]==0) Global->MinSize[key]=index[counter].dwSize; //Audio Data if(tc=='w'){ Audio->Number[key]++; Audio->TotalSize[key]+=index[counter].dwSize; if(index[counter].dwSize>Audio->MaxSize[key]) Audio->MaxSize[key]=index[counter].dwSize; if(index[counter].dwSizeMinSize[key] || Audio->MinSize[key]==0) Audio->MinSize[key]=index[counter].dwSize; } //Video Data if(tc=='d'){ Video->Number[key]++; Video->TotalSize[key]+=index[counter].dwSize; if(index[counter].dwSize>Video->MaxSize[key]) Video->MaxSize[key]=index[counter].dwSize; if(index[counter].dwSizeMinSize[key] || Video->MinSize[key]==0) Video->MinSize[key]=index[counter].dwSize; } if (key){ //if k/f - repeat counting for global records. flag=1; key=0; }else{ flag=0; } } } }