uint8_t asfHeader::open(const char *name) { _fd=ADM_fopen(name,"rb"); if(!_fd) { GUI_Error_HIG("File Error.","Cannot open file\n"); return 0; } myName=ADM_strdup(name); if(!getHeaders()) { return 0; } ADM_info("Stream Video: index=%d, sid=%d\n",(int)_videoIndex,(int)_videoStreamId); for(int i=0;i<_nbAudioTrack;i++) ADM_info("Stream Audio: index=%d, sid=%d\n", (int)_allAudioTracks[i].streamIndex,(int)_allAudioTracks[i].streamIndex); buildIndex(); fseeko(_fd,_dataStartOffset,SEEK_SET); _packet=new asfPacket(_fd,_nbPackets,_packetSize,&readQueue,&storageQueue,_dataStartOffset); curSeq=1; for(int i=0;i<_nbAudioTrack;i++) { _audioAccess[i]=new asfAudioAccess(this,i); _audioStreams[i]=ADM_audioCreateStream(&(_allAudioTracks[i].wavHeader), _audioAccess[i]); } if(!nbImage) { ADM_error("No image found \n"); return 0; } return 1; }
/** \fn create \brief actually create the track, can fail */ bool ADM_edAudioTrackExternal::create(uint32_t extraLen, uint8_t *extraData) { ADM_info("Initializing audio track from external %s \n",sourceFile.c_str()); codec=getAudioCodec(wavHeader.encoding,&wavHeader,extraLen,extraData);; size=internalAccess->getLength(); internalAudioStream=ADM_audioCreateStream(&wavHeader,internalAccess,true); return true; }
uint8_t wtvHeader::open(const char *name) { _fd=ADM_fopen(name,"rb"); if(!_fd) { GUI_Error_HIG("File Error.","Cannot open file\n"); return 0; } return false; for(int i=0;i<_nbAudioTrack;i++) { _audioAccess[i]=new wtvAudioAccess(this,i); _audioStreams[i]=ADM_audioCreateStream(&(_allAudioTracks[i].wavHeader), _audioAccess[i]); } return 1; }
uint8_t tsHeader::open(const char *name) { char *idxName=(char *)malloc(strlen(name)+6); bool r=false; FP_TYPE appendType=FP_DONT_APPEND; uint32_t append; char *type; uint64_t startDts; uint32_t version=0; sprintf(idxName,"%s.idx2",name); indexFile index; if(!index.open(idxName)) { printf("[tsDemux] Cannot open index file %s\n",idxName); free(idxName); return false; } if(!index.readSection("System")) { printf("[tsDemux] Cannot read system section\n"); goto abt; } type=index.getAsString("Type"); if(!type || type[0]!='T') { printf("[tsDemux] Incorrect or not found type\n"); goto abt; } version=index.getAsUint32("Version"); if(version!=ADM_INDEX_FILE_VERSION) { GUI_Error_HIG("Error","This file's index has been created with an older version of avidemux.\nPlease delete the idx2 file and reopen."); goto abt; } append=index.getAsUint32("Append"); printf("[tsDemux] Append=%"PRIu32"\n",append); if(append) appendType=FP_APPEND; if(!parser.open(name,&appendType)) { printf("[tsDemux] Cannot open root file (%s)\n",name); goto abt; } if(!readVideo(&index)) { printf("[tsDemux] Cannot read Video section of %s\n",idxName); goto abt; } if(!readAudio(&index,name)) { printf("[tsDemux] Cannot read Audio section of %s => No audio\n",idxName); } if(!readIndex(&index)) { printf("[tsDemux] Cannot read index for file %s\n",idxName); goto abt; } updateIdr(); updatePtsDts(); _videostream.dwLength= _mainaviheader.dwTotalFrames=ListOfFrames.size(); printf("[tsDemux] Found %d video frames\n",_videostream.dwLength); if(_videostream.dwLength)_isvideopresent=1; //*********** tsPacket=new tsPacketLinear(videoPid); if(tsPacket->open(name,appendType)==false) { printf("tsDemux] Cannot tsPacket open the file\n"); goto abt; } r=true; for(int i=0;i<listOfAudioTracks.size();i++) { ADM_tsTrackDescriptor *desc=listOfAudioTracks[i]; ADM_audioStream *audioStream=ADM_audioCreateStream(&desc->header,desc->access); if(!audioStream) { }else { desc->stream=audioStream; audioStream->setLanguage(desc->language); } } abt: free(idxName); index.close(); printf("[tsDemuxer] Loaded %d\n",r); return r; }
/** \fn open */ uint8_t OpenDMLHeader::open(const char *name) { uint8_t badAvi=0; uint32_t rd; printf("** opening OpenDML files **"); _fd=ADM_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("%x != %x\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 %"PRIu64" (%"PRIx64") size : %"PRIu64" (%"PRIx64")\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("[AVI]Mmm(1) we have a bogey here, size mismatch : %"PRIu64"\n",_Tracks[i].strh.size); printf("[AVI]expected %d\n",(int)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("[AVI]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 %u\n",i); break; } } if(0xff==vidTrack) { printf("Could not identify video track!"); return 0; } // 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("[AVI]bih is not big enough (%"PRIu64"/%d)!\n",_Tracks[vidTrack].strf.size,(int)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]; _audioStreams=new ADM_audioStream *[_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("[AVI]Mmm(2) we have a bogey here, size mismatch : %"PRIu64"\n",_Tracks[run].strh.size); printf("[AVI]expected %d\n",(int)sizeof(_audiostream)); if(_Tracks[run].strh.size<sizeof(_audiostream)-8) { GUI_Error_HIG(QT_TR_NOOP("Malformed header"), NULL); return 0; } printf("[AVI]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("[AVI]WavHeader is not big enough (%"PRIu64"/%d)!\n", _Tracks[run].strf.size,(int)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 { 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) { ADM_warning("Fixing audio track to be PCM\n"); hdr->frequency=48000; //hdr->channels=2; hdr->byterate=48000*hdr->channels*2; hdr->blockalign=2*hdr->channels; } } } // build audio stream for(int i=0;i<_nbAudioTracks;i++) { track=&(_audioTracks[i]); ADM_aviAudioAccess *access=new ADM_aviAudioAccess(track->index,track->wavHeader, track->nbChunks, myName, track->extraDataLen,track->extraData); _audioStreams[i]= ADM_audioCreateStream((track->wavHeader), access); } } if(!_video_bih.biCompression && fourCC::check(_videostream.fccHandler,(uint8_t*)"DIB ")) { _videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t*)"DIB "); } else _videostream.fccHandler=_video_bih.biCompression; printf("\nOpenDML file successfully read..\n"); if(ret==1) { computePtsDts(); removeEmptyFrames(); } ADM_info("PtsAvailable : %d\n",(int)ptsAvailable); return ret; }
//______________________________________ // // Open and recursively read the atoms // until we got the information we want // i.e. : // index for audio and video track // esds for mpeg4 // size / codec used // // We don't care about sync atom and all // other stuff which are pretty useless on // 3gp file anyway. //______________________________________ uint8_t MP4Header::open(const char *name) { printf("** opening 3gpp files **"); _fd=ADM_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); _videostream.dwScale=1000; _videostream.dwRate=10000; _mainaviheader.dwMicroSecPerFrame=100000;; // 10 fps hard coded adm_atom *atom=new adm_atom(_fd); // Some mp4/mov files have the data at the end but do start properly // detect and workaround... // Check it is not mdat start(ADM_memcpy_0) uint8_t check[4]; uint64_t fileSize; fseeko(_fd,0,SEEK_END); fileSize=ftello(_fd); fseeko(_fd,4,SEEK_SET); fread(check,4,1,_fd); fseeko(_fd,0,SEEK_SET); if(check[0]=='m' && check[1]=='d' &&check[2]=='a' && check[3]=='t') { uint64_t of; uint64_t hi,lo; printf("Data first, header later...\n"); of=atom->read32(); if(of==1) { atom->read32(); // size atom->read32(); // fcc hi=atom->read32(); lo=atom->read32(); of=(hi<<32)+lo; if(of>fileSize) of=hi; } fseeko(_fd,of,SEEK_SET); printf("Header starts at %"PRIx64"\n",of); delete atom; atom=new adm_atom(_fd); } //************** if(!lookupMainAtoms((void*) atom)) { printf("Cannot find needed atom\n"); fclose(_fd); _fd=NULL; delete atom; return 0; } delete atom; _isvideopresent=1; _isaudiopresent=0; _videostream.fccType=fourCC::get((uint8_t *)"vids"); _video_bih.biBitCount=24; _videostream.dwInitialFrames= 0; _videostream.dwStart= 0; printf("\n"); if(!VDEO.index) { printf("No index!\n"); return 0; } // If it is mpeg4 and we have extra data // Decode vol header to get the real width/height // The mpeg4/3GP/Mov header is often misleading if(fourCC::check(_videostream.fccHandler,(uint8_t *)"DIVX")) { if(VDEO.extraDataSize) { uint32_t w,h,ti; if(extractMpeg4Info(VDEO.extraData,VDEO.extraDataSize,&w,&h,&ti)) { printf("MP4 Corrected size : %"PRIu32" x %"PRIu32"\n",w,h); _video_bih.biWidth=_mainaviheader.dwWidth=w ; _video_bih.biHeight=_mainaviheader.dwHeight=h; } }else { printf("No extradata to probe\n");} } else { /* Same story for H263 : Analyze 1st frame to get the real width/height */ if(fourCC::check(_videostream.fccHandler,(uint8_t *)"H263")) { uint32_t w,h,sz; uint8_t *bfer=NULL; sz=VDEO.index[0].size; if(sz) { bfer=new uint8_t[sz]; ADMCompressedImage img; img.data=bfer; if(getFrame(0,&img)) { if(extractH263Info(bfer,sz,&w,&h)) { printf("H263 Corrected size : %"PRIu32" x %"PRIu32"\n",w,h); _video_bih.biWidth=_mainaviheader.dwWidth=w ; _video_bih.biHeight=_mainaviheader.dwHeight=h; } else { printf("H263 COULD NOT EXTRACT SIZE, using : %"PRIu32" x %"PRIu32"\n", _video_bih.biWidth, _video_bih.biHeight); } } delete [] bfer; } } } /* * Veryfy DTS<=PTS */ int nb=(int)_tracks[0].nbIndex; uint64_t delta,maxDelta=0; for(int i=0;i<nb;i++) { uint64_t pts,dts; dts=VDEO.index[i].dts; pts=VDEO.index[i].pts; if(pts==ADM_COMPRESSED_NO_PTS || dts==ADM_COMPRESSED_NO_PTS) continue; if(dts>=pts) { uint64_t delta=(uint64_t)(dts-pts); if(delta>maxDelta) maxDelta=delta; } } if(maxDelta) { shiftTimeBy(maxDelta); _movieDuration+=(maxDelta+999)/1000; } /* Now build audio tracks */ if(nbAudioTrack) _isaudiopresent=1; // Still needed ? adjustElstDelay(); // for(int audio=0;audio<nbAudioTrack;audio++) { switch(_tracks[1+audio]._rdWav.encoding) { // Lookup if AAC is lying about # of channels case WAV_AAC: { if(_tracks[1+audio].extraDataSize==2) { // Channels uint32_t word=(_tracks[1+audio].extraData[0]<<8)+_tracks[1+audio].extraData[1]; uint32_t chan=(word>>3)&0xf; uint32_t fqIndex=(word>>7)&0xf; printf("0x%x word, Channel : %d, fqIndex=%d\n",word,chan,fqIndex); } } break; case WAV_AC3: // same for ac3 { // read First chunk MP4Index *dex=_tracks[1+audio].index; int size=dex[0].size; uint8_t *buffer=new uint8_t[size]; fseeko(_fd,dex[0].offset,SEEK_SET); if(fread(buffer,1,size,_fd)) { uint32_t fq, br, chan, syncoff; if(ADM_AC3GetInfo(buffer,size, &fq, &br, &chan,&syncoff)) { ADM_info("Updating AC3 info : Fq=%d, br=%d, chan=%d\n",fq,br,chan); _tracks[1+audio]._rdWav.channels=chan; _tracks[1+audio]._rdWav.byterate=br; } } delete [] buffer; } break; default: break; } audioAccess[audio]=new ADM_mp4AudioAccess(name,&(_tracks[1+audio])); audioStream[audio]=ADM_audioCreateStream(&(_tracks[1+audio]._rdWav), audioAccess[audio]); }
/** \fn open */ uint8_t avsHeader::open(const char *name) { if(!network.bindMe(9999)) { printf("[avsProxy]Open failed\n"); return 0; } // now time to grab some info avsInfo info; avsNetPacket in,out; out.buffer=(uint8_t *)&info; out.sizeMax=sizeof(info); out.size=0; typedef struct { uint32_t ver; uint32_t api; }version; version v={AVSHEADER_API_VERSION,6}; in.buffer=(uint8_t *)&v; in.size=sizeof(v); in.sizeMax=sizeof(v); if(!network.command(AvsCmd_GetInfo,0,&in,&out)) { printf("Get info failed\n"); return 0; } // Dump some info #define PINFO(x) printf(#x":%d\n",info.x); PINFO( version); PINFO( width); PINFO( height); PINFO( fps1000); PINFO( nbFrames); PINFO( frequency); PINFO( channels); // Build header.. _isaudiopresent = 0; // Remove audio ATM _isvideopresent = 1; // Remove audio ATM #define CLR(x) memset(& x,0,sizeof( x)); if(!info.width || !info.fps1000 || !info.height) { ADM_error("Wrong width/height/fps\n"); return false; } if(info.version!=AVSHEADER_API_VERSION) { GUI_Error_HIG("","Wrong API version, expected %d, got %d\n",AVSHEADER_API_VERSION,info.version); return false; } CLR(_videostream); CLR(_mainaviheader); _videostream.dwScale = 1000; _videostream.dwRate = info.fps1000; _mainaviheader.dwMicroSecPerFrame = 40000;; // 25 fps hard coded _videostream.fccType = fourCC::get((uint8_t *) "YV12"); _video_bih.biBitCount = 24; _videostream.dwLength = _mainaviheader.dwTotalFrames = info.nbFrames; _videostream.dwInitialFrames = 0; _videostream.dwStart = 0; // //_video_bih.biCompression= 24; // _video_bih.biWidth = _mainaviheader.dwWidth = info.width; _video_bih.biHeight = _mainaviheader.dwHeight = info.height; _video_bih.biCompression = _videostream.fccHandler = fourCC::get((uint8_t *) "YV12"); // if(info.frequency) { wavHeader.frequency=info.frequency; wavHeader.channels=info.channels; wavHeader.bitspersample=16; wavHeader.blockalign=info.channels*2; wavHeader.byterate=info.frequency*2*info.channels; wavHeader.encoding=WAV_PCM; audioAccess=new ADM_avsAccess(&network,&wavHeader,10000); _isaudiopresent=1; if(audioAccess) audioStream=ADM_audioCreateStream(&wavHeader,audioAccess); if(audioStream) { ADM_info("Created audio stream\n"); haveAudio=true; } else ADM_warning("Error when creating audio stream\n"); } printf("Connection to avsproxy succeed\n"); return 1; }
uint8_t psHeader::open(const char *name) { char *idxName=(char *)malloc(strlen(name)+6); bool r=false; FP_TYPE appendType=FP_DONT_APPEND; uint32_t append; char *type; uint64_t startDts; uint32_t version=0; sprintf(idxName,"%s.idx2",name); indexFile index; if(!index.open(idxName)) { printf("[psDemux] Cannot open index file %s\n",idxName); free(idxName); return false; } if(!index.readSection("System")) { printf("[psDemux] Cannot read system section\n"); goto abt; } version=index.getAsUint32("Version"); if(version!=ADM_INDEX_FILE_VERSION) { GUI_Error_HIG(QT_TRANSLATE_NOOP("psdemuxer","Error"), QT_TRANSLATE_NOOP("psdemuxer","This file's index has been created with an older version of avidemux.\nPlease delete the idx2 file and reopen.")); goto abt; } type=index.getAsString("Type"); if(!type || type[0]!='P') { printf("[psDemux] Incorrect or not found type\n"); goto abt; } append=index.getAsUint32("Append"); printf("[psDemux] Append=%" PRIu32"\n",append); if(append) appendType=FP_APPEND; if(!parser.open(name,&appendType)) { printf("[psDemux] Cannot open root file %s\n",name); goto abt; } if(!readVideo(&index)) { printf("[psDemux] Cannot read Video section of %s\n",idxName); goto abt; } if(!readAudio(&index,name)) { printf("[psDemux] Cannot read Audio section of %s => No audio\n",idxName); } if(!readIndex(&index)) { printf("[psDemux] Cannot read index for file %s\n",idxName); goto abt; } if(readScrReset(&index)) { ADM_info("Adjusting timestamps\n"); // Update PTS/DTS of video taking SCR Resets into account int nbPoints=listOfScrGap.size(); int index=0; uint64_t pivot=listOfScrGap[0].position; uint64_t timeOffset=0; uint32_t nbImage=ListOfFrames.size(); for(int i=0;i<nbImage;i++) { dmxFrame *frame=ListOfFrames[i]; if(frame->startAt>pivot) // next gap { timeOffset=listOfScrGap[index].timeOffset; index++; if(index>=nbPoints) pivot=0xfffffffffffffffLL; else pivot=listOfScrGap[index].position; } if(frame->dts!=ADM_NO_PTS) frame->dts+=timeOffset; if(frame->pts!=ADM_NO_PTS) frame->pts+=timeOffset; } ADM_info("Adjusted %d scr reset out of %d\n",(int)index,(int)nbPoints); ADM_info("Updating audio with list of SCR\n"); for(int i=0;i<listOfAudioTracks.size();i++) listOfAudioTracks[i]->access->setScrGapList(&listOfScrGap) ; } updatePtsDts(); _videostream.dwLength= _mainaviheader.dwTotalFrames=ListOfFrames.size(); printf("[psDemux] Found %d video frames\n",_videostream.dwLength); if(_videostream.dwLength)_isvideopresent=1; //*********** psPacket=new psPacketLinear(0xE0); if(psPacket->open(name,appendType)==false) { printf("psDemux] Cannot psPacket open the file\n"); goto abt; } r=true; for(int i=0;i<listOfAudioTracks.size();i++) { ADM_psTrackDescriptor *desc=listOfAudioTracks[i]; ADM_audioStream *audioStream=ADM_audioCreateStream(&desc->header,desc->access); if(!audioStream) { }else { desc->stream=audioStream; } } abt: index.close(); free(idxName); printf("[psDemuxer] Loaded %d\n",r); return r; }
uint8_t flvHeader::open(const char *name) { uint32_t prevLen, type, size, pts,pos=0; _isvideopresent=0; _isaudiopresent=0; audioTrack=NULL; videoTrack=NULL; _videostream.dwRate=0; _filename=ADM_strdup(name); _fd=fopen(name,"rb"); if(!_fd) { printf("[FLV] Cannot open %s\n",name); return 0; } // Get size uint32_t fileSize=0; fseeko(_fd,0,SEEK_END); fileSize=ftello(_fd); fseeko(_fd,0,SEEK_SET); printf("[FLV] file size :%u bytes\n",fileSize); // It must begin by F L V 01 uint8_t four[4]; read(4,four); if(four[0]!='F' || four[1]!='L' || four[2]!='V') { printf("[FLV] Not a flv file %s\n",name); return 0; } // Next one is flags uint32_t flags=read8(); if(flags & 1) // VIDEO { _isvideopresent=1; printf("[FLV] Video flag\n"); } else { GUI_Info_HIG(ADM_LOG_INFO,"Warning","This FLV file says it has no video.\nI will assume it has and try to continue"); _isvideopresent=1; } if(flags & 4) // Audio { _isaudiopresent=1; printf("[FLV] Audio flag\n"); } // Skip header uint32_t skip=read32(); fseeko(_fd,skip,SEEK_SET); printf("[FLV] Skipping %u header bytes\n",skip); pos=ftello(_fd);; printf("pos:%u/%u\n",pos,fileSize); // Create our video index videoTrack=new flvTrak(50); if(_isaudiopresent) audioTrack=new flvTrak(50); else audioTrack=NULL; // Loop while(pos<fileSize-14) { pos=ftello(_fd); prevLen=read32(); type=read8(); size=read24(); pts=read24(); read32(); // ??? uint32_t remaining=size; //printf("[FLV] At %08x found type %x size %u pts%u\n",pos,type,size,pts); switch(type) { case FLV_TAG_TYPE_AUDIO: { if(!_isaudiopresent) { audioTrack=new flvTrak(50); _isaudiopresent=1; /* Damn lying headers...*/ }; uint8_t flags=read8(); int of=1+4+3+3+1+4; remaining--; int format=flags>>4; int fq=(flags>>2)&3; int bps=(flags>>1) & 1; int channel=(flags) & 1; if(!audioTrack->_nbIndex) // first frame.. { setAudioHeader(format,fq,bps,channel); } insertAudio(pos+of,remaining,pts); } break; case FLV_TAG_TYPE_META: parseMetaData(remaining); remaining=0; break; case FLV_TAG_TYPE_VIDEO: { int of=1+4+3+3+1+4; uint8_t flags=read8(); remaining--; int frameType=flags>>4; int codec=(flags)&0xf; if(codec==FLV_CODECID_VP6) { read8(); // 1 byte of extraData remaining--; of++; } int first=0; if(!videoTrack->_nbIndex) first=1; insertVideo(pos+of,remaining,frameType,pts); if(first) // first frame.. { if(!setVideoHeader(codec,&remaining)) return 0; } } break; default: printf("[FLV]At 0x%x, unhandled type %u\n",pos,type); } Skip(remaining); } // while // Udpate frame count etc.. printf("[FLV] Found %u frames\n",videoTrack->_nbIndex); _videostream.dwLength= _mainaviheader.dwTotalFrames=videoTrack->_nbIndex; // Compute average fps float f=_videostream.dwLength; uint64_t duration=videoTrack->_index[videoTrack->_nbIndex-1].timeCodeUs; if(duration) f=1000.*1000.*1000.*f/duration; else f=25000; // If it was available from the metadata, use the one from metadata if(! _videostream.dwRate) { float d=searchMinimum(); printf("[FLV] minimum delta :%d\n",(uint32_t)d); d=1/d; d*=1000*1000*1000; uint32_t avg=(uint32_t)floor(f); uint32_t max=(uint32_t)floor(d); if(max<2) max=2; // 500 fps max printf("[FLV] Avg fps :%d, max fps :%d\n",avg,max); _videostream.dwRate=max; } _videostream.dwScale=1000; _mainaviheader.dwMicroSecPerFrame=ADM_UsecFromFps1000(_videostream.dwRate); printf("[FLV] Duration %"LLU" ms\n",videoTrack->_index[videoTrack->_nbIndex-1].timeCodeUs/1000); // _videostream.fccType=fourCC::get((uint8_t *)"vids"); _video_bih.biBitCount=24; _videostream.dwInitialFrames= 0; _videostream.dwStart= 0; videoTrack->_index[0].flags=AVI_KEY_FRAME; // audio track if(_isaudiopresent) { ADM_flvAccess *access=new ADM_flvAccess(name,audioTrack); _audioStream=ADM_audioCreateStream(&wavHeader,access); } else { _audioStream = NULL; access=NULL; } printf("[FLV]FLV successfully read\n"); return 1; }
//______________________________________ // // Open and recursively read the atoms // until we got the information we want // i.e. : // index for audio and video track // esds for mpeg4 // size / codec used // // We don't care about sync atom and all // other stuff which are pretty useless on // 3gp file anyway. //______________________________________ uint8_t MP4Header::open(const char *name) { printf("** opening 3gpp 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); _videostream.dwScale=1000; _videostream.dwRate=10000; _mainaviheader.dwMicroSecPerFrame=100000;; // 10 fps hard coded adm_atom *atom=new adm_atom(_fd); // Some mp4/mov files have the data at the end but do start properly // detect and workaround... // Check it is not mdat start(ADM_memcpy_0) uint8_t check[4]; fseeko(_fd,4,SEEK_SET); fread(check,4,1,_fd); fseeko(_fd,0,SEEK_SET); if(check[0]=='m' && check[1]=='d' &&check[2]=='a' && check[3]=='t') { uint64_t of; printf("Data first, header later...\n"); of=atom->read32(); if(of==1) { atom->read32(); // size atom->read32(); // fcc of=atom->read64(); } fseeko(_fd,of,SEEK_SET); printf("Header starts at %"LLX"\n",of); delete atom; atom=new adm_atom(_fd); } //************** if(!lookupMainAtoms((void*) atom)) { printf("Cannot find needed atom\n"); fclose(_fd); delete atom; return 0; } delete atom; _isvideopresent=1; _isaudiopresent=0; _videostream.fccType=fourCC::get((uint8_t *)"vids"); _video_bih.biBitCount=24; _videostream.dwInitialFrames= 0; _videostream.dwStart= 0; printf("\n"); if(!VDEO.index) { printf("No index!\n"); return 0; } // If it is mpeg4 and we have extra data // Decode vol header to get the real width/height // The mpeg4/3GP/Mov header is often misleading if(fourCC::check(_videostream.fccHandler,(uint8_t *)"DIVX")) { if(VDEO.extraDataSize) { uint32_t w,h,ti; if(extractMpeg4Info(VDEO.extraData,VDEO.extraDataSize,&w,&h,&ti)) { printf("MP4 Corrected size : %"LU" x %"LU"\n",w,h); _video_bih.biWidth=_mainaviheader.dwWidth=w ; _video_bih.biHeight=_mainaviheader.dwHeight=h; } }else { printf("No extradata to probe\n");} } else { /* Same story for H263 : Analyze 1st frame to get the real width/height */ if(fourCC::check(_videostream.fccHandler,(uint8_t *)"H263")) { uint32_t w,h,sz; uint8_t *bfer=NULL; sz=VDEO.index[0].size; if(sz) { bfer=new uint8_t[sz]; ADMCompressedImage img; img.data=bfer; if(getFrame(0,&img)) { if(extractH263Info(bfer,sz,&w,&h)) { printf("H263 Corrected size : %"LU" x %"LU"\n",w,h); _video_bih.biWidth=_mainaviheader.dwWidth=w ; _video_bih.biHeight=_mainaviheader.dwHeight=h; } else { printf("H263 COULD NOT EXTRACT SIZE, using : %"LU" x %"LU"\n", _video_bih.biWidth, _video_bih.biHeight); } } delete [] bfer; } } } /* Now build audio tracks */ if(nbAudioTrack) _isaudiopresent=1; // Still needed ? for(int audio=0;audio<nbAudioTrack;audio++) { audioAccess[audio]=new ADM_mp4AudioAccess(name,&(_tracks[1+audio])); audioStream[audio]=ADM_audioCreateStream(&(_tracks[1+audio]._rdWav), audioAccess[audio]); } fseeko(_fd,0,SEEK_SET); printf("3gp/mov file successfully read..\n"); return 1; }