bool asfHeader::loadAudio(asfChunk *s,uint32_t sid) { asfAudioTrak *trk=&(_allAudioTracks[_nbAudioTrack]); ADM_assert(_nbAudioTrack<ASF_MAX_AUDIO_TRACK); trk->streamIndex=sid; s->read((uint8_t *)&(trk->wavHeader),sizeof(WAVHeader)); printf("[Asf] Encoding for audio 0x%x\n",trk->wavHeader.encoding); #ifdef ADM_BIG_ENDIAN Endian_WavHeader(&(trk->wavHeader)); #endif trk->extraDataLen=s->read16(); printf("Extension :%u bytes\n",trk->extraDataLen); if(trk->extraDataLen) { trk->extraData=new uint8_t[trk->extraDataLen]; s->read(trk->extraData,trk->extraDataLen); } printf("#block in group :%d\n",s->read8()); printf("#byte in group :%d\n",s->read16()); printf("Align1 :%d\n",s->read16()); printf("Align2 :%d\n",s->read16()); _nbAudioTrack++; return true; }
//_________________________________________________________ // Write header if needed //_________________________________________________________ uint8_t AVDMGenericAudioStream::writeHeader(FILE * out) { WAVHeader wh, *last_wave; last_wave = getInfo(); if (last_wave->encoding != WAV_PCM) return 1; _LAll = new AviList("RIFF", out); _LAll->Begin("WAVE"); memcpy(&wh, last_wave, sizeof(WAVHeader)); // update Header wh.encoding = WAV_PCM; wh.blockalign = 2 * wh.channels; wh.bitspersample = 16; wh.byterate = last_wave->frequency * last_wave->channels * 2; // Do it for little endian Endian_WavHeader(&wh); // _LAll->WriteChunk((uint8_t *) "fmt ", sizeof(WAVHeader), (uint8_t *) & wh); _LAll->Write32("data"); // size to be completed later _dlen = _LAll->Tell(); _LAll->Write32((uint32_t) 0L); return 1; }
//______________________________________ // // Open and get the headears/index built // along way //______________________________________ uint8_t OpenDMLHeader::open(const char *name) { uint8_t badAvi=0; uint32_t rd; printf("** opening OpenDML files **"); _fd=fopen(name,"rb"); if(!_fd) { printf("\n cannot open %s \n",name); return 0; } myName=ADM_strdup(name); #define CLR(x) memset(& x,0,sizeof( x)); CLR( _videostream); CLR( _mainaviheader); _isvideopresent=1; _isaudiopresent=0; _nbTrack=0; riffParser *parser=new riffParser(name); if(MKFCC('R','I','F','F')!=(rd=parser->read32())) { printf("Not riff\n");badAvi=1; printf("%lx != %lx\n",rd,MKFCC('R','I','F','F')); } parser->read32(); if(MKFCC('A','V','I',' ')!=parser->read32()) { printf("Not Avi\n");badAvi=1; } if(!badAvi) { walk(parser); } delete parser; aprintf("Found %d tracks\n:-----------\n",_nbTrack); // check if it looks like a correct avi if(!_nbTrack) badAvi=1; // if we are up to here -> good avi :) if(badAvi) { printf("FAIL\n"); return 0; } // now read up each parts... //____________________________ #ifdef __WIN32 #define DUMP_TRACK(i) aprintf(" at %I64u (%I64x) size : %I64u (%I64x)\n", \ _Tracks[i].strh.offset,\ _Tracks[i].strh.offset,\ _Tracks[i].strh.size,\ _Tracks[i].strh.size); #else #define DUMP_TRACK(i) aprintf(" at %llu (%llx) size : %llu (%llx)\n", \ _Tracks[i].strh.offset,\ _Tracks[i].strh.offset,\ _Tracks[i].strh.size,\ _Tracks[i].strh.size); #endif for(uint32_t i=0;i<_nbTrack;i++) { DUMP_TRACK(i); } uint32_t vidTrack=0xff; // search wich track is the video one // and load it to _videoheader for(uint32_t i=0;i<_nbTrack;i++) { fseeko(_fd,_Tracks[i].strh.offset,SEEK_SET); if(_Tracks[i].strh.size!=sizeof(_videostream)) { printf("Mmm(1) we have a bogey here, size mismatch : %"LLU"\n",_Tracks[i].strh.size); printf("expected %d\n",sizeof(_videostream)); if(_Tracks[i].strh.size<sizeof(_videostream)-8) // RECT is not mandatory { GUI_Error_HIG(QT_TR_NOOP("Malformed header"), NULL); return 0; } printf("Trying to continue anyway\n"); } fread(&_videostream,sizeof(_videostream),1,_fd); #ifdef ADM_BIG_ENDIAN Endian_AviStreamHeader(&_videostream); #endif if(_videostream.fccType==MKFCC('v','i','d','s')) { vidTrack=i; printf("Video track is %ld\n",i); break; } } if(0xff==vidTrack) { printf("Could not identify video track!"); return 0; } // STOP HERE -> Alex <- //return 0; // STOP HERE -> Alex <- // then bih stuff int32_t extra; // _fd=fopen(name,"rb"); fseeko(_fd,_Tracks[vidTrack].strf.offset,SEEK_SET); extra=_Tracks[vidTrack].strf.size-sizeof(_video_bih); if(extra<0) { printf("bih is not big enough (%lu/%lu)!\n",_Tracks[vidTrack].strf.size,sizeof(_video_bih)); return 0; } fread(&_video_bih,sizeof(_video_bih),1,_fd); #ifdef ADM_BIG_ENDIAN Endian_BitMapInfo(&_video_bih); #endif if(extra>0) { _videoExtraLen=extra; _videoExtraData=new uint8_t [extra]; fread(_videoExtraData,extra,1,_fd); } _isvideopresent=1; //-------------------------------------------------- // Read audio trak info, select if there is // several //-------------------------------------------------- // and audio track if(_mainaviheader.dwStreams>=2) { // which one is the audio track, is there several ? if(!(_nbAudioTracks=countAudioTrack())) { printf("Weird, there is no audio track, but more than one stream...\n"); } else { uint32_t run=0,audio=0; odmlAudioTrack *track; _audioTracks=new odmlAudioTrack[_nbAudioTracks]; while(audio<_nbAudioTracks) { ADM_assert(run<_nbTrack); track=&(_audioTracks[audio]); fseeko(_fd,_Tracks[run].strh.offset,SEEK_SET); if(_Tracks[run].strh.size != sizeof(_audiostream)) { printf("Mmm(2) we have a bogey here, size mismatch : %"LLU"\n",_Tracks[run].strh.size); printf("expected %d\n",sizeof(_audiostream)); if(_Tracks[run].strh.size<sizeof(_audiostream)-8) { GUI_Error_HIG(QT_TR_NOOP("Malformed header"), NULL); return 0; } printf("Trying to continue anyway\n"); } fread(track->avistream,sizeof(_audiostream),1,_fd); #ifdef ADM_BIG_ENDIAN Endian_AviStreamHeader(track->avistream); #endif if(track->avistream->fccType!=MKFCC('a','u','d','s')) { printf("Not an audio track!\n"); run++; continue; } // now read extra stuff fseeko(_fd,_Tracks[run].strf.offset,SEEK_SET); extra=_Tracks[run].strf.size-sizeof(WAVHeader); if(extra<0) { printf("WavHeader is not big enough (%lu/%lu)!\n", _Tracks[run].strf.size,sizeof(WAVHeader)); return 0; } fread(track->wavHeader,sizeof(WAVHeader),1,_fd); #ifdef ADM_BIG_ENDIAN Endian_WavHeader(track->wavHeader); #endif if(extra>2) { fgetc(_fd);fgetc(_fd); extra-=2; track->extraDataLen=extra; track->extraData=new uint8_t [extra]; fread(track->extraData,extra,1,_fd); } track->trackNum=run; audio++; run++; } } } // now look at the index stuff // there could be 3 cases: // 1- It is a openDML index, meta index + several smaller index // 2- It is a legacy index (type 1 , most common) // 3- It is a broken index or no index at all // // If it is a openDML index we will find a "indx" field in the Tracks // Else we will find it in _regularIndex Track // Since openDML often also have a regular index we will try open DML first uint8_t ret=0; Dump(); // take the size of riff header and actual file size uint64_t riffSize; fseeko(_fd,0,SEEK_END); _fileSize=ftello(_fd); fseeko(_fd,0,SEEK_SET); read32(); riffSize=(uint64_t )read32(); // 1st case, we have an avi < 4 Gb // potentially avi type 1 #if 0 if((_fileSize<4*1024*1024*1024LL)&& // if riff size is ~ fileSize try regular index (abs(riffSize-_fileSize)<1024*1024)) #endif #define HAS(x) if(x) printf(#x" : yes\n"); else printf(#x" : no\n"); // If there is no openDML index HAS( _regularIndex.offset); HAS( _Tracks[vidTrack].indx.offset); if(!ret && _regularIndex.offset &&!_Tracks[vidTrack].indx.offset) // try regular avi if a idx1 field is there (avi index) ret=indexRegular(vidTrack); if (!ret && _Tracks[vidTrack].indx.offset) // Try openDML if a index field is there (openDML) ret=indexODML(vidTrack); if(!ret) { printf("Could not index it properly...\n"); return 0; } if(!_nbAudioTracks) { _isaudiopresent=0; } else { // build audio stream odmlAudioTrack *track; // Check it is not a weird DV file if(fourCC::check(_video_bih.biCompression,(uint8_t *)"dvsd")) { for(int i=0;i<_nbAudioTracks;i++) { track=&(_audioTracks[i]); WAVHeader *hdr= track->wavHeader; if(!hdr->frequency) { printf("Fixing audio track to be PCM\n"); hdr->frequency=48000; //hdr->channels=2; hdr->byterate=48000*hdr->channels*2; hdr->blockalign=2*hdr->channels; } } } for(int i=0;i<_nbAudioTracks;i++) { track=&(_audioTracks[i]); _audioTracks[i].track= new AVDMAviAudioStream(track->index, track->nbChunks, myName, track->wavHeader, 0, track->extraDataLen,track->extraData); } } if (!_video_bih.biCompression && fourCC::check(_videostream.fccHandler,(uint8_t*)"DIB ")) { // flip video uint8_t *extraData = new uint8_t[_videoExtraLen + 9]; memcpy(extraData, _videoExtraData, _videoExtraLen); memcpy(extraData + _videoExtraLen, "BottomUp", 9); delete [] _videoExtraData; _videoExtraLen += 9; _videoExtraData = extraData; _videostream.fccHandler = _video_bih.biCompression = fourCC::get((uint8_t*)"DIB "); } else _videostream.fccHandler=_video_bih.biCompression; printf("\nOpenDML file successfully read..\n"); return ret; }
//______________________________________ // // Open and get the headears/index built // along way //______________________________________ uint8_t OpenDMLHeader::open(char *name) { uint8_t badAvi=0; uint32_t rd; printf("** opening OpenDML files **"); _fd=fopen(name,"rb"); if(!_fd) { printf("\n cannot open %s \n",name); return 0; } #define CLR(x) memset(& x,0,sizeof( x)); CLR( _videostream); CLR( _mainaviheader); _isvideopresent=1; _isaudiopresent=0; _nbTrack=0; riffParser *parser=new riffParser(name); if(MKFCC('R','I','F','F')!=(rd=parser->read32())) { printf("Not riff\n");badAvi=1; printf("%lx != %lx\n",rd,MKFCC('R','I','F','F')); } parser->read32(); if(MKFCC('A','V','I',' ')!=parser->read32()) { printf("Not Avi\n");badAvi=1; } if(!badAvi) { walk(parser); } delete parser; aprintf("Found %d tracks\n:-----------\n",_nbTrack); // check if it looks like a correct avi if(!_nbTrack) badAvi=1; // if we are up to here -> good avi :) if(badAvi) { printf("FAIL\n"); return 0; } // now read up each parts... //____________________________ #define DUMP_TRACK(i) aprintf(" at %llu (%llx) size : %llu (%llx)\n", \ _Tracks[i].strh.offset,\ _Tracks[i].strh.offset,\ _Tracks[i].strh.size,\ _Tracks[i].strh.size); for(uint32_t i=0;i<_nbTrack;i++) { DUMP_TRACK(i); } uint32_t vidTrack=0xff; // search wich track is the video one // and load it to _videoheader for(uint32_t i=0;i<_nbTrack;i++) { fseeko(_fd,_Tracks[i].strh.offset,SEEK_SET); if(_Tracks[i].strh.size!=sizeof(_videostream)) { printf("Mmm(1) we have a bogey here, size mismatch : %lu \n",_Tracks[i].strh.size); printf("expected %d\n",sizeof(_videostream)); if(_Tracks[i].strh.size<sizeof(_videostream)-8) // RECT is not mandatory { GUI_Alert("Maformed header!"); return 0; } printf("Trying to continue anyway\n"); } fread(&_videostream,sizeof(_videostream),1,_fd); #ifdef ADM_BIG_ENDIAN Endian_AviStreamHeader(&_videostream); #endif if(_videostream.fccType==MKFCC('v','i','d','s')) { vidTrack=i; printf("Video track is %ld\n",i); break; } } if(0xff==vidTrack) { printf("Could not identify video track!"); return 0; } // STOP HERE -> Alex <- //return 0; // STOP HERE -> Alex <- // then bih stuff int32_t extra; _fd=fopen(name,"rb"); fseeko(_fd,_Tracks[vidTrack].strf.offset,SEEK_SET); extra=_Tracks[vidTrack].strf.size-sizeof(_video_bih); if(extra<0) { printf("bih is not big enough (%lu/%lu)!\n",_Tracks[vidTrack].strf.size,sizeof(_video_bih)); return 0; } fread(&_video_bih,sizeof(_video_bih),1,_fd); #ifdef ADM_BIG_ENDIAN Endian_BitMapInfo(&_video_bih); #endif if(extra>0) { _videoExtraLen=extra; _videoExtraData=new uint8_t [extra]; fread(_videoExtraData,extra,1,_fd); } _isvideopresent=1; //-------------------------------------------------- // Read audio trak info, select if there is // several //-------------------------------------------------- // and audio track uint32_t audioTrack=0xff; uint32_t audioTrackNumber=0; if(_mainaviheader.dwStreams>=2) { // which one is the audio track, is there several ? switch(countAudioTrack()) { case 0: printf("No audio track found.\n"); break; case 1: printf("One audio track found\n"); audioTrack=searchAudioTrack(0); audioTrackNumber=0; break; default: printf("Several audio tracks found\n"); uint32_t t; t=GUI_Question("Take second audio track ?"); audioTrackNumber=t; audioTrack=searchAudioTrack(t); } if(audioTrack!=0xff) // one is marked { // Read information printf("Taking audio track : %lu %lu\n",audioTrackNumber,audioTrack); _isaudiopresent=1; fseeko(_fd,_Tracks[audioTrack].strh.offset,SEEK_SET); if(_Tracks[audioTrack].strh.size!=sizeof(_audiostream)); { printf("Mmm(2) we have a bogey here, size mismatch : %lu \n" ,_Tracks[audioTrack].strh.size); printf("expected %d\n",sizeof(_audiostream)); if(_Tracks[audioTrack].strh.size<sizeof(_audiostream)-8) { GUI_Alert("Maformed header!"); return 0; } printf("Trying to continue anyway\n"); } fread(&_audiostream,sizeof(_audiostream),1,_fd); #ifdef ADM_BIG_ENDIAN Endian_AviStreamHeader(&_audiostream); #endif if(_audiostream.fccType!=MKFCC('a','u','d','s')) { printf("Not an audio track!\n"); return 0; } // now read extra stuff fseeko(_fd,_Tracks[audioTrack].strf.offset,SEEK_SET); extra=_Tracks[audioTrack].strf.size-sizeof(_wavHeader); if(extra<0) { printf("WavHeader is not big enough (%lu/%lu)!\n", _Tracks[audioTrack].strf.size,sizeof(WAVHeader)); return 0; } fread(&_wavHeader,sizeof(WAVHeader),1,_fd); #ifdef ADM_BIG_ENDIAN Endian_WavHeader(&_wavHeader); #endif if(extra>2) { fgetc(_fd);fgetc(_fd); extra-=2; _audioExtraLen=extra; _audioExtraData=new uint8_t [extra]; fread(_audioExtraData,extra,1,_fd); } } } // now look at the index stuff // there could be 3 cases: // 1- It is a openDML index, meta index + several smaller index // 2- It is a legacy index (type 1 , most common) // 3- It is a broken index or no index at all // // If it is a openDML index we will find a "indx" field in the Tracks // Else we will find it in _regularIndex Track // Since openDML often also have a regular index we will try open DML first uint8_t ret=0; Dump(); // take the size of riff header and actual file size uint64_t riffSize; fseeko(_fd,0,SEEK_END); _fileSize=ftello(_fd); fseeko(_fd,0,SEEK_SET); read32(); riffSize=(uint64_t )read32(); // 1st case, we have an avi < 4 Gb // potentially avi type 1 if((_fileSize<4*1024*1024*1024LL)&& // if riff size is ~ fileSize try regular index (abs(riffSize-_fileSize)<1024*1024)) { printf("Size looks good, maybe type 1 avi\n"); if(!ret && !_Tracks[vidTrack].indx.offset) // try regular avi ret=indexRegular(vidTrack,audioTrack,audioTrackNumber); if (!ret && _Tracks[vidTrack].indx.offset) ret=indexODML(vidTrack,audioTrack,audioTrackNumber); if(!ret) // re-index! ret=indexReindex(vidTrack,audioTrack,audioTrackNumber); } // else try openDML/reindexing else { printf("Size mismatch, not type 1 avi\n"); if (!ret && _Tracks[vidTrack].indx.offset) ret=indexODML(vidTrack,audioTrack,audioTrackNumber); if(!ret) // re-index! ret=indexReindex(vidTrack,audioTrack,audioTrackNumber); } if(!ret) { printf("Cound not index it properly...\n"); return 0; } if(!_audioIdx) _isaudiopresent=0; else { // build audio stream _audioTrack = new AVDMAviAudioStream(_audioIdx, _nbAudioChunk, _fd, &_wavHeader, 0, _audioExtraLen,_audioExtraData); } _videostream.fccHandler=_video_bih.biCompression; printf("\nOpenDML file successfully read..\n"); return ret; }
//________________________________________________ // Beginning of the write process // We fill-in the headers // 3- Write audio headers // That one can be used several times so we pass stuff // as parameter //_______________________________________________ uint8_t aviWrite::writeAudioHeader ( AVDMGenericAudioStream * stream, AVIStreamHeader *header ) { WAVHeader *wav=NULL; // pre compute some headers with extra data in... uint8_t wmaheader[12]; VBRext mp3vbr; uint8_t *extra=NULL; uint32_t extraLen=0; if(!stream) return 1; memset(wmaheader,0,12); memset(&mp3vbr,0,sizeof(mp3vbr)); wmaheader[16-16]=0x0a; wmaheader[19-16]=0x08; wmaheader[22-16]=0x01; wmaheader[24-16]=0x74; wmaheader[25-16]=01; wav = stream->getInfo (); assert (wav); memset (header, 0, sizeof (AVIStreamHeader)); header->fccType = fourCC::get ((uint8_t *) "auds"); header->dwInitialFrames = 0; header->dwStart = 0; header->dwRate = wav->byterate; header->dwSampleSize = 1; header->dwQuality = 0xffffffff; header->dwSuggestedBufferSize = 8000; header->dwLength = stream->getLength (); switch(wav->encoding) { case WAV_MP3: // then update VBR fields mp3vbr.cbsize = R16(12); mp3vbr.wId = R16(1); mp3vbr.fdwflags = R32(2); mp3vbr.nframesperblock = R16(1); mp3vbr.ncodecdelay = 0; wav->bitspersample = 0; mp3vbr.nblocksize=R16(0x180); //383; // ?? header->dwScale = 1; header->dwInitialFrames = 1; if (wav->blockalign ==1152) // VBR audio { // We do like nandub do //assert (audiostream->asTimeTrack ()); wav->blockalign = 1152; // just a try wav->bitspersample = 16; header->dwRate = wav->frequency; //wav->byterate; header->dwScale = wav->blockalign; header->dwLength= _videostream.dwLength; header->dwSampleSize = 0; printf ("\n VBR audio detected\n"); // // use extended headers // // double nb; nb = stream->getLength (); nb/= _videostream.dwLength; // avg value of a block (i.e. a mpeg frame) mp3vbr.nblocksize = (uint32_t) floor (nb); mp3vbr.nblocksize = R16(mp3vbr.nblocksize); } else wav->blockalign=1; extra=(uint8_t *)&mp3vbr; extraLen=sizeof(mp3vbr); break; case WAV_WMA: header->dwScale = wav->blockalign; header->dwSampleSize = wav->blockalign; header->dwInitialFrames =1; header->dwSuggestedBufferSize=10*wav->blockalign; extra=(uint8_t *)&wmaheader; extraLen=12; break; default: header->dwScale = 1; wav->blockalign=1; break; } #ifdef ADM_BIG_ENDIAN // in case of Little endian, do the usual swap crap AVIStreamHeader as; WAVHeader w; memcpy(&as,header,sizeof(as)); Endian_AviStreamHeader(&as); memcpy(&w,wav,sizeof(w)); Endian_WavHeader( &w ); setStreamInfo (_out, (uint8_t *) &as, (uint8_t *)&w,sizeof(WAVHeader), extra,extraLen, 0x1000); #else setStreamInfo (_out, (uint8_t *) header, (uint8_t *) wav, sizeof (WAVHeader), extra,extraLen, 0x1000); #endif return 1; }