uint8_t asfHeader::loadVideo(asfChunk *s) { uint32_t w,h,x; w=s->read32(); h=s->read32(); s->read8(); x=s->read16(); _isvideopresent=1; memset(&_mainaviheader,0,sizeof(_mainaviheader)); _mainaviheader.dwWidth=w; _mainaviheader.dwHeight=h; _video_bih.biWidth=w; _video_bih.biHeight=h; printf("Pic Width %04d\n",w); printf("Pic Height %04d\n",h); printf(" BMP size %04d (%04d)\n",x,sizeof(BITMAPINFOHEADER)); s->read((uint8_t *)&_video_bih,sizeof(BITMAPINFOHEADER)); _videostream.dwScale=1000; _videostream.dwRate=30000; _videostream.fccHandler=_video_bih.biCompression; printf("Codec : <%s> (%04x)\n", fourCC::tostring(_video_bih.biCompression),_video_bih.biCompression); if(fourCC::check(_video_bih.biCompression,(uint8_t *)"DVR ")) { // It is MS DVR, fail so that the mpeg2 indexer can take it from here _videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t *)"MPEG"); printf("This is MSDVR, not ASF\n"); return 0; } printBih(&_video_bih); if(x>sizeof(BITMAPINFOHEADER)) { _extraDataLen=x-sizeof(BITMAPINFOHEADER); _extraData=new uint8_t[_extraDataLen]; s->read(_extraData,_extraDataLen); } return 1; }
void OpenDMLHeader::Dump( void ) { printf( "Main header\n" ); printf( "______________________\n" ); #define X_DUMP(x) printf(#x":\t\t:%ld\n",_mainaviheader.x); X_DUMP(dwStreams); X_DUMP(dwMicroSecPerFrame) ; X_DUMP(dwMaxBytesPerSec); X_DUMP(dwPaddingGranularity); X_DUMP(dwFlags); X_DUMP(dwTotalFrames); X_DUMP(dwInitialFrames); X_DUMP(dwWidth); X_DUMP(dwHeight); printf("\n"); #undef X_DUMP #define X_DUMP(x) printf("\n "#x":\t\t:%ld",_videostream.x); printf( "video stream attached:\n" ); printf( "______________________\n" ); printf(" Extra Data : %ld",_videoExtraLen); if(_videoExtraLen) { mixDump( _videoExtraData, _videoExtraLen); } printf("\n fccType :"); fourCC::print(_videostream.fccType); printf("\n fccHandler :"); fourCC::print(_videostream.fccHandler); X_DUMP(dwFlags); X_DUMP(dwInitialFrames); X_DUMP(dwRate); X_DUMP(dwStart); X_DUMP(dwSampleSize); X_DUMP(dwScale); X_DUMP(dwLength); X_DUMP(dwQuality); X_DUMP(dwSampleSize); printf("\n"); printBih(&_video_bih); /***************************************************************** Dump infos about all audio tracks found ******************************************************************/ for(int i=0;i<_nbAudioTracks;i++) { #undef X_DUMP #define X_DUMP(x) printf("\n "#x":\t\t:%ld",_audioTracks[i].avistream->x); printf( "\naudio stream attached:\n" ); printf( "______________________\n" ); printf("\n fccType :"); fourCC::print(_audioTracks[i].avistream->fccType); printf("\n fccHandler :"); fourCC::print(_audioTracks[i].avistream->fccHandler); printf("\n fccHandler :0x%lx", _audioTracks[i].avistream->fccHandler); X_DUMP(dwFlags); X_DUMP(dwInitialFrames); X_DUMP(dwRate); X_DUMP(dwScale); X_DUMP(dwStart); X_DUMP(dwLength); X_DUMP(dwSuggestedBufferSize); X_DUMP(dwQuality); X_DUMP(dwSampleSize); #undef X_DUMP printWavHeader(_audioTracks[i].wavHeader); printf(" Extra Data : %ld\n",_audioTracks[i].extraDataLen); if(_audioTracks[i].extraDataLen) { mixDump( _audioTracks[i].extraData, _audioTracks[i].extraDataLen); } printf("\n"); } }
uint8_t asfHeader::loadVideo(asfChunk *s) { uint32_t w,h,x; printf("--\n"); w=s->read32(); h=s->read32(); s->read8(); x=s->read16(); _isvideopresent=1; memset(&_mainaviheader,0,sizeof(_mainaviheader)); _mainaviheader.dwWidth=w; _mainaviheader.dwHeight=h; _video_bih.biWidth=w; _video_bih.biHeight=h; printf("Pic Width %04d\n",w); printf("Pic Height %04d\n",h); printf(" BMP size %04d (%04d)\n",x,(int)sizeof(ADM_BITMAPINFOHEADER)); s->read((uint8_t *)&_video_bih,sizeof(ADM_BITMAPINFOHEADER)); #ifdef ADM_BIG_ENDIAN Endian_BitMapInfo(&_video_bih); #endif _videostream.fccHandler=_video_bih.biCompression; printf("Codec : <%s> (%04x)\n", fourCC::tostring(_video_bih.biCompression),_video_bih.biCompression); if(fourCC::check(_video_bih.biCompression,(uint8_t *)"DVR ")) { // It is MS DVR, fail so that the mpeg2 indexer can take it from here _videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t *)"MPEG"); printf("This is MSDVR, not ASF\n"); return 0; } printBih(&_video_bih); #if 1 if(_video_bih.biSize>sizeof(ADM_BITMAPINFOHEADER)) { x=_video_bih.biSize; #else if(x>sizeof(ADM_BITMAPINFOHEADER)) { #endif _videoExtraLen=x-sizeof(ADM_BITMAPINFOHEADER); _videoExtraData=new uint8_t[_videoExtraLen]; s->read(_videoExtraData,_videoExtraLen); ADM_info("We have %d bytes of extra data for video.\n",(int)_videoExtraLen); }else { ADM_info("No extra data for video\n"); } uint64_t l=ftello(_fd); printf("Bytes left : %d\n",(int)(s->endPos()-l)); return 1; } /** \fn buildIndex \brief Scan the file to build an index Header Chunk Chunk Chunk Chunk Data chunk Chunk Chunk We skip the 1st one, and just read the header of the 2nd one */ uint8_t asfHeader::buildIndex(void) { uint32_t fSize; const chunky *id; uint32_t chunkFound; uint32_t r=5; uint32_t len; fseeko(_fd,0,SEEK_END); fSize=ftello(_fd); fseeko(_fd,0,SEEK_SET); asfChunk h(_fd); printf("[ASF] ********** Building index **********\n"); printf("[ASF] Searching data\n"); while(r--) { h.nextChunk(); // Skip headers id=h.chunkId(); h.dump(); if(id->id==ADM_CHUNK_DATA_CHUNK) break; h.skipChunk(); } if(id->id!=ADM_CHUNK_DATA_CHUNK) return 0; // Remove leftover from DATA_chunk // Unknown GUID 16 // Number of packets UINT64 8 // Unknown UINT8 1 // Unknown UINT8 1 // h.read32(); h.read32(); h.read32(); h.read32(); _nbPackets=(uint32_t) h.read64(); h.read16(); len=h.chunkLen-16-8-2-24; printf("[ASF] nbPacket : %u\n",_nbPackets); printf("[ASF] len to go : %u\n",len); printf("[ASF] scanning data\n"); _dataStartOffset=ftello(_fd); // Here we go asfPacket *aPacket=new asfPacket(_fd,_nbPackets,_packetSize, &readQueue,&storageQueue,_dataStartOffset); uint32_t packet=0; #define MAXIMAGE (_nbPackets) uint32_t sequence=0; uint32_t ceilImage=MAXIMAGE; nbImage=0; len=0; asfIndex indexEntry; memset(&indexEntry,0,sizeof(indexEntry)); bool first=true; DIA_workingBase *progressBar=createWorking("Indexing"); uint32_t fileSizeMB=(uint32_t)(fSize>>10); uint64_t lastDts[ASF_MAX_AUDIO_TRACK]; for(int i=0;i<ASF_MAX_AUDIO_TRACK;i++) { lastDts[i]=0; } while(packet<_nbPackets) { while(readQueue.size()) { asfBit *bit=NULL; // update UI uint32_t curPos=(uint32_t)(ftello(_fd)>>10); progressBar->update(curPos,fileSizeMB); bit=readQueue.front(); readQueue.pop_front(); // -- uint64_t dts=bit->dts; uint64_t pts=bit->pts; aprintf("** DTS=%s\n",ADM_us2plain(dts)); aprintf("** PDTS=%s\n",ADM_us2plain(pts)); if(bit->stream==_videoStreamId) { aprintf(">found video packet of size=%d off=%d seq %d, while curseq =%d, dts=%s", bit->len,bit->offset, bit->sequence,curSeq, ADM_us2plain(dts)); aprintf(" pts=%s\n",ADM_us2plain(pts)); if(bit->sequence!=sequence || first==true) { if(first==false) { indexEntry.frameLen=len; aprintf("Pushing video frame index=%d seq=%d pts=%s \n", _index.size(), indexEntry.segNb,ADM_us2plain(indexEntry.pts)); aprintf("dts=%s\n",ADM_us2plain(indexEntry.dts)); _index.append(indexEntry); } aprintf("New sequence\n"); if( ((sequence+1)&0xff)!=(bit->sequence&0xff)) { ADM_warning("!!!!!!!!!!!! non continuous sequence %u %u\n",sequence,bit->sequence); } indexEntry.frameLen=0; indexEntry.segNb=bit->sequence; indexEntry.packetNb=bit->packet; indexEntry.flags=bit->flags; indexEntry.dts=dts; indexEntry.pts=pts; if(first==false) { sequence=bit->sequence; readQueue.push_front(bit); // reuse it next time len=0; continue; }else { sequence=bit->sequence; first=false; // first packet } } len+=bit->len; } // End of video stream Id else // Audio ? { int found=0; for(int i=0;i<_nbAudioTrack && !found;i++) { if(bit->stream == _allAudioTracks[i].streamIndex) { if(bit->pts!=ADM_NO_PTS) { if(!lastDts[i] || (bit->pts>lastDts[i]+500000L)) // seek point every 500 ms { asfAudioSeekPoint seek; seek.pts=bit->pts; seek.packetNb=bit->packet; (audioSeekPoints[i]).append(seek); #if 1 if(!lastDts[i]) printf("Adding seek point for track %d at %s (packet=%d)\n", i,ADM_us2plain(bit->pts),(int)seek.packetNb); #endif lastDts[i]=bit->pts; aprintf("Adding seek point for track %d at %s (packet=%d)\n", i,ADM_us2plain(bit->pts),(int)seek.packetNb); } } found=1; } } if(!found) { printf("Unmapped stream %u\n",bit->stream); } } delete [] bit->data; bit->data=NULL; storageQueue.push_back(bit); } //working->update(packet,_nbPackets); packet++; aPacket->nextPacket(0xff); // All packets aPacket->skipPacket(); } delete progressBar; delete aPacket; //delete working; /* Compact index */ fseeko(_fd,_dataStartOffset,SEEK_SET); printf("[ASF] %u images found\n",nbImage); printf("[ASF] ******** End of buildindex *******\n"); nbImage=_index.size();; if(!nbImage) return 0; uint64_t shift=60*1000*1000; bool canShift=false; uint64_t tPts; tPts=_index[0].pts; ADM_info("First image pts: %s, dts: %s\n",ADM_us2plain(tPts), ADM_us2plain(_index[0].dts)); if(tPts != ADM_NO_PTS) { shift=tPts; ADM_info("Video shift = %s\n",ADM_us2plain(tPts)); canShift=true; }else canShift=false; for(int i=0;i<_nbAudioTrack;i++) { if(!audioSeekPoints[i].size()) { ADM_info("audio track : %d, no seek\n",i); canShift=false; continue; } tPts=audioSeekPoints[i][0].pts; ADM_info("audio track : %d, %s\n",i,ADM_us2plain(tPts)); if(tPts<shift) shift=tPts; } if(canShift) { ADM_info("Shifting a/v raw=%s\n",ADM_us2plain(shift)); }else { ADM_info("Can t shift\n"); shift=0; } _videostream.dwLength=_mainaviheader.dwTotalFrames=nbImage; _index[0].flags=AVI_KEY_FRAME; if(_index[0].pts==ADM_NO_PTS) _index[0].pts=_index[0].dts; // Update fps // In fact it is an average fps // _videostream.dwScale=1000; // check if we have a duration per frame for video... int n=frameDurationMapping.size(); int dex=-1; for(int i=0;i<n;i++) { if(frameDurationMapping[i].streamNb==_videoStreamId) dex=i; } if(dex!=-1) { ADM_info("Average fps provided\n"); setFps(frameDurationMapping[dex].usPerFrame); } else { ADM_info("Fps not provided, guessing it from nbFrame and duration\n"); uint32_t avgFps; if(_index[nbImage-1].pts!=ADM_NO_PTS && _index[0].pts!=ADM_NO_PTS) { float f=(_index[nbImage-1].pts-_index[0].pts); f/=nbImage; // average duration of 1 image in us setFps((uint64_t) f); }else { printf("[Asf] No pts, setting 30 fps hardcoded\n"); _videostream.dwRate=(uint32_t)30000;; } } if(shift) { double frames3=_videostream.dwScale; frames3/=_videostream.dwRate; frames3*=3*1000*1000; // ADM_info("3 frames time = %s\n",ADM_us2plain((uint64_t)frames3)); uint64_t frame64=(uint64_t)frames3; if(frame64<shift) shift=shift-frame64; else shift=0; shiftAudioVideoBy(shift); } return 1; }