void GameUIConfig::SaveVideosOptions() { QRect res = rec_Resolution(); setValue("videorec/format", AVFormat()); setValue("videorec/videocodec", videoCodec()); setValue("videorec/audiocodec", audioCodec()); setValue("videorec/framerate", rec_Framerate()); setValue("videorec/bitrate", rec_Bitrate()); setValue("videorec/width", res.width()); setValue("videorec/height", res.height()); setValue("videorec/usegameres", Form->ui.pageOptions->checkUseGameRes->isChecked()); setValue("videorec/audio", recordAudio()); sync(); }
/** \fn parseStbl \brief parse sample table. this is the most important function. */ uint8_t MP4Header::parseStbl(void *ztom,uint32_t trackType,uint32_t w,uint32_t h,uint32_t trackScale) { adm_atom *tom=(adm_atom *)ztom; ADMAtoms id; uint32_t container; MPsampleinfo info; memset(&info,0,sizeof(info)); printf("<<Parsing Stbl>>\n"); while(!tom->isDone()) { adm_atom son(tom); if(!ADM_mp4SearchAtomName(son.getFCC(), &id,&container)) { adm_printf(ADM_PRINT_DEBUG,"[STBL]Found atom %s unknown\n",fourCC::tostringBE(son.getFCC())); son.skipAtom(); continue; } switch(id) { case ADM_MP4_STSS: // Sync sample atom (i.e. keyframes) { son.read32(); info.nbSync=son.read32(); printf("Stss:%u\n",info.nbSync); if(info.nbSync) { info.Sync=new uint32_t[info.nbSync]; for(int i=0;i<info.nbSync;i++) { info.Sync[i]=son.read32(); } } break; } case ADM_MP4_STTS: { printf("stts:%lu\n",son.read32()); // version & flags info.nbStts=son.read32(); printf("Time stts atom found (%lu)\n",info.nbStts); printf("Using myscale %lu\n",trackScale); info.SttsN=new uint32_t[info.nbStts]; info.SttsC=new uint32_t[info.nbStts]; double dur; for(int i=0;i<info.nbStts;i++) { info.SttsN[i]=son.read32(); info.SttsC[i]=son.read32(); adm_printf(ADM_PRINT_VERY_VERBOSE,"stts: count:%u size:%u (unscaled)\n",info.SttsN[i],info.SttsC[i]); //dur*=1000.*1000.;; // us //dur/=myScale; } } break; case ADM_MP4_STSC: { son.read32(); info.nbSc=son.read32(); info.Sc=new uint32_t[info.nbSc]; info.Sn=new uint32_t[info.nbSc]; for(int j=0;j<info.nbSc;j++) { info.Sc[j]=son.read32(); info.Sn[j]=son.read32(); son.read32(); adm_printf(ADM_PRINT_VERY_VERBOSE,"\t sc %d : sc start:%u sc count: %u\n",j,info.Sc[j],info.Sn[j]); } } break; case ADM_MP4_STSZ: { uint32_t n; son.read32(); n=son.read32(); info.nbSz=son.read32(); info.SzIndentical=0; printf("%lu frames /%lu nbsz..\n",n,info.nbSz); if(n) { adm_printf(ADM_PRINT_VERY_VERBOSE,"\t\t%lu frames of the same size %lu , n=%lu\n", info.nbSz,info.SzIndentical,n); info.SzIndentical=n; info.Sz=NULL; } else { info.Sz=new uint32_t[info.nbSz]; for(int j=0;j<info.nbSz;j++) { info.Sz[j]=son.read32(); } } } break; case ADM_MP4_CTTS: // Composition time to sample { uint32_t n,i,j,k,v; printf("ctts:%lu\n",son.read32()); // version & flags n=son.read32(); if(n==1) // all the same , ignore { break; } uint32_t *values=new uint32_t [n]; uint32_t *count=new uint32_t [n]; for(i=0;i<n;i++) { count[i]=son.read32(); values[i]=son.read32(); } uint32_t sum=0; for(i=0;i<n;i++) { sum+=count[i]; } info.Ctts=new uint32_t[sum+1]; // keep a safe margin for(i=0;i<n;i++) { if(i<20) { adm_printf(ADM_PRINT_VERY_VERBOSE,"Ctts: nb: %u (%x) val:%u (%x)\n",count[i],count[i],values[i],values[i]); } for(k=0;k<count[i];k++) { info.Ctts[info.nbCtts++]=values[i]; } } delete [] values; delete [] count; if(!info.nbCtts) { delete [] info.Ctts; info.Ctts=NULL; printf("Destroying Ctts, seems invalid\n"); } ADM_assert(info.nbCtts<sum+1); printf("Found %u elements\n",info.nbCtts); } break; case ADM_MP4_STCO: { son.read32(); info.nbCo=son.read32(); printf("\t\tnbCo:%u\n",info.nbCo); info.Co=new uint32_t[info.nbCo]; for(int j=0;j< info.nbCo;j++) { info.Co[j]=son.read32(); adm_printf(ADM_PRINT_VERY_VERBOSE,"Chunk offset : %u / %u : %u\n", j,info.nbCo,info.Co[j]); } } break; case ADM_MP4_STCO64: { printf("Incomplete support for 64 bits quicktime!!\n"); son.read32(); info.nbCo=son.read32(); printf("\t\tnbCo:%u\n",info.nbCo); info.Co=new uint32_t[info.nbCo]; for(int j=0;j< info.nbCo;j++) { son.read32(); // Ignore MSB info.Co[j]=son.read32(); adm_printf(ADM_PRINT_VERY_VERBOSE,"Chunk offset : %u / %u : %lu\n", j,info.nbCo,info.Co[j]); } } break; case ADM_MP4_STSD: { son.read32(); // flags & version int nbEntries=son.read32(); int left; adm_printf(ADM_PRINT_DEBUG,"[STSD]Found %d entries\n",nbEntries); for(int i=0;i<nbEntries;i++) { int entrySize=son.read32(); int entryName=son.read32(); left=entrySize-8; if(i || (trackType==TRACK_VIDEO && _videoFound) || (trackType==TRACK_OTHER)) { son.skipBytes(left); printf("[STSD] ignoring %s, size %u\n",fourCC::tostringBE(entryName),entrySize); if(trackType==TRACK_OTHER) printf("[STSD] because track=other\n"); continue; } switch(trackType) { case TRACK_VIDEO: { uint32_t lw=0,lh=0; printf("[STSD] VIDEO %s, size %u\n",fourCC::tostringBE(entryName),entrySize); son.skipBytes(8); // reserved etc.. left-=8; son.read32(); // version/revision left-=4; printf("[STSD] vendor %s\n",fourCC::tostringBE(son.read32())); left-=4; son.skipBytes(8); // spatial qual etc.. left-=8; printf("[STSD] width :%u\n",lw=son.read16()); printf("[STSD] height :%u\n",lh=son.read16()); left-=4; son.skipBytes(8); // Resolution left-=8; printf("[STSD] datasize :%u\n",son.read32()); left-=4; printf("[STSD] FrameCount :%u\n",son.read16()); left-=4; // Codec name uint32_t u32=son.read(); if(u32>31) u32=31; printf("Codec string :%d <",u32); for(int i=0;i<u32;i++) printf("%c",son.read()); printf(">\n"); son.skipBytes(32-1-u32); left-=32; // son.read32(); left-=4; //Depth & color Id // printf("LEFT:%d\n",left); if(left>8) { // decodeVideoAtom(&son); } // #define commonPart(x) _videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t *)#x); _video_bih.biWidth=_mainaviheader.dwWidth=lw ; _video_bih.biHeight=_mainaviheader.dwHeight=lh; _video_bih.biCompression=_videostream.fccHandler; // switch(entryName) { case MKFCCR('m','j','p','b'): //mjpegb { commonPart(MJPB); left=0; } break; case MKFCCR('s','2','6','3'): //s263 d263 { commonPart(H263); adm_atom d263(&son); printf("Reading s253, got %s\n",fourCC::tostringBE(d263.getFCC())); left=0; } break; case MKFCCR('m','p','4','v'): //mp4v { commonPart(DIVX); adm_atom esds(&son); printf("Reading esds, got %s\n",fourCC::tostringBE(esds.getFCC())); if(esds.getFCC()==MKFCCR('e','s','d','s')) decodeEsds(&esds,TRACK_VIDEO); left=0; } break; case MKFCCR('S','V','Q','3'): {//'SVQ3': // For SVQ3, the codec needs it to begin by SVQ3 // We go back by 4 bytes to get the 4CC printf("SVQ3 atom found\n"); VDEO.extraDataSize=left+4; VDEO.extraData=new uint8_t[ VDEO.extraDataSize ]; if(!son.readPayload(VDEO.extraData+4,VDEO.extraDataSize-4 )) { GUI_Error_HIG(QT_TR_NOOP("Problem reading SVQ3 headers"), NULL); } VDEO.extraData[0]='S'; VDEO.extraData[1]='V'; VDEO.extraData[2]='Q'; VDEO.extraData[3]='3'; printf("SVQ3 Header size : %lu",_videoExtraLen); commonPart(SVQ3); left=0; } break; case MKFCCR('d','v','c',' ') : //'dvc ': case MKFCCR('d','v','c','p'): //'dvcp': commonPart(DVDS); break; case MKFCCR('c','v','i','d'): //'cvid' commonPart(cvid); break; case MKFCCR('h','2','6','3'): //'dv': commonPart(H263); break; case MKFCCR('M','J','P','G'): //'jpeg': case MKFCCR('j','p','e','g'): //'jpeg': case MKFCCR('A','V','D','J'): //'jpeg': commonPart(MJPG); break; case MKFCCR('a','v','c','1'): // avc1 { commonPart(H264); // There is a avcC atom just after // configuration data for h264 adm_atom avcc(&son); printf("Reading avcC, got %s\n",fourCC::tostringBE(avcc.getFCC())); int len,offset; VDEO.extraDataSize=avcc.getRemainingSize(); VDEO.extraData=new uint8_t [VDEO.extraDataSize]; avcc.readPayload(VDEO.extraData,VDEO.extraDataSize); printf("avcC size:%d\n",VDEO.extraDataSize); // Dump some info #define MKD8(x) VDEO.extraData[x] #define MKD16(x) ((MKD8(x)<<8)+MKD8(x+1)) #define MKD32(x) ((MKD16(x)<<16)+MKD16(x+2)) printf("avcC Revision :%x\n", MKD8(0)); printf("avcC AVCProfileIndication :%x\n", MKD8(1)); printf("avcC profile_compatibility:%x\n", MKD8(2)); printf("avcC AVCLevelIndication :%x\n", MKD8(3)); printf("avcC lengthSizeMinusOne :%x\n", MKD8(4)); printf("avcC NumSeq :%x\n", MKD8(5)); len=MKD16(6); printf("avcC sequenceParSetLen :%x ",len ); offset=8; mixDump(VDEO.extraData+offset,len); offset=8+len; printf("\navcC numOfPictureParSets :%x\n", MKD8(offset++)); len=MKD16(offset++); printf("avcC Pic len :%x\n",len); mixDump(VDEO.extraData+offset,len); left=0; } break; default: if(left>10) { adm_atom avcc(&son); printf("Reading , got %s\n",fourCC::tostringBE(avcc.getFCC())); left=0; } break; } // Entry name } break; case TRACK_AUDIO: { uint32_t channels,bpp,encoding,fq,packSize; // Put some defaults ADIO.encoding=1234; ADIO.frequency=44100; ADIO.byterate=128000>>3; ADIO.channels=2; ADIO.bitspersample=16; printf("[STSD] AUDIO <%s>, 0x%08x, size %u\n",fourCC::tostringBE(entryName),entryName,entrySize); son.skipBytes(8); // reserved etc.. left-=8; int atomVersion=son.read16(); // version left-=2; printf("[STSD]Revision :%d\n",atomVersion); son.skipBytes(2); // revision left-=2; printf("[STSD]Vendor : %s\n",fourCC::tostringBE(son.read32())); left-=4; ADIO.channels=channels=son.read16(); // Channel left-=2; printf("[STSD]Channels :%d\n",ADIO.channels); ADIO.bitspersample=bpp=son.read16(); // version/revision left-=2; printf("[STSD]Bit per sample :%d\n",bpp); encoding=son.read16(); // version/revision left-=2; printf("[STSD]Encoding :%d\n",encoding); packSize=son.read16(); // Packet Size left-=2; printf("[STSD]Packet size :%d\n",encoding); fq=ADIO.frequency=son.read16(); printf("[STSD]Fq:%u\n",fq); if(ADIO.frequency<6000) ADIO.frequency=48000; printf("[STSD]Fq :%d\n",ADIO.frequency); // Bps son.skipBytes(2); // Fixed point left-=4; if(atomVersion) { info.samplePerPacket=son.read32(); info.bytePerPacket=son.read32(); info.bytePerFrame=son.read32(); printf("[STSD] Sample per packet %u\n",info.samplePerPacket); printf("[STSD] Bytes per packet %u\n",info.bytePerPacket); printf("[STSD] Bytes per frame %u\n",info.bytePerFrame); printf("[STSD] Bytes per sample %u\n",son.read32()); left-=16; }else { info.samplePerPacket=1; info.bytePerPacket=1; info.bytePerFrame=1; } switch(atomVersion) { case 0:break; case 1: break; case 2: ADIO.frequency=44100; // FIXME ADIO.channels=son.read32(); printf("Channels :%d\n",ADIO.channels); // Channels printf("Tak(7F000) :%x\n",son.read32()); // Channels printf("Bits per channel :%d\n",son.read32()); // Vendor printf("Format specific :%x\n",son.read32()); // Vendor printf("Byte per audio packe:%x\n",son.read32()); // Vendor printf("LPCM :%x\n",son.read32()); // Vendor left-=(5*4+4+16); break; } printf("[STSD] chan:%u bpp:%u encoding:%u fq:%u (left %u)\n",channels,bpp,encoding,fq,left); #define audioCodec(x) ADIO.encoding=WAV_##x; switch(entryName) { case MKFCCR('t','w','o','s'): audioCodec(LPCM); ADIO.byterate=ADIO.frequency*ADIO.bitspersample*ADIO.channels/8; break; case MKFCCR('u','l','a','w'): audioCodec(ULAW); ADIO.byterate=ADIO.frequency; break; case MKFCCR('s','o','w','t'): audioCodec(PCM); ADIO.byterate=ADIO.frequency*ADIO.bitspersample*ADIO.channels/8; break; case MKFCCR('.','m','p','3'): //.mp3 audioCodec(MP3); ADIO.byterate=128000>>3; break; case MKFCCR('r','a','w',' '): audioCodec(8BITS_UNSIGNED); ADIO.byterate=ADIO.frequency*ADIO.channels; break; case MKFCCR('s','a','m','r'): { audioCodec(AMRNB); ADIO.frequency=8000; ADIO.channels=1; ADIO.bitspersample=16; ADIO.byterate=12000/8; if(left>10) { adm_atom amr(&son); printf("Reading wave, got %s\n",fourCC::tostringBE(amr.getFCC())); left=0; } } break; case MKFCCR('Q','D','M','2'): { uint32_t sz; audioCodec(QDM2); sz=son.getRemainingSize(); _tracks[1+nbAudioTrack].extraDataSize=sz; _tracks[1+nbAudioTrack].extraData=new uint8_t[sz]; son.readPayload(_tracks[1+nbAudioTrack].extraData,sz); left=0; } break; case MKFCCR('m','s',0,0x55): // why 55 ??? case MKFCCR('m','p','4','a'): { audioCodec(AAC); if(left>10) { adm_atom wave(&son); printf("Reading wave, got %s\n",fourCC::tostringBE(wave.getFCC())); if(MKFCCR('w','a','v','e')==wave.getFCC()) { // mp4a // wave // frma // mp4a // esds while(!wave.isDone()) { adm_atom item(&wave); printf("parsing wave, got %s,0x%x\n",fourCC::tostringBE(item.getFCC()), item.getFCC()); switch(item.getFCC()) { case MKFCCR('f','r','m','a'): { uint32_t codecid=item.read32(); printf("frma Codec Id :%s\n",fourCC::tostringBE(codecid)); } break; case MKFCCR('m','s',0,0x55): { // We have a waveformat here printf("[STSD]Found MS audio header:\n"); ADIO.encoding=ADM_swap16(item.read16()); ADIO.channels=ADM_swap16(item.read16()); ADIO.frequency=ADM_swap32(item.read32()); ADIO.byterate=ADM_swap32(item.read32()); ADIO.blockalign=ADM_swap16(item.read16()); ADIO.bitspersample=ADM_swap16(item.read16()); printWavHeader(&(ADIO)); } break; case MKFCCR('m','p','4','a'): break; case MKFCCR('e','s','d','s'): { decodeEsds(&item,TRACK_AUDIO); goto foundit; // FIXME!!! } break; default: break; } item.skipAtom(); } // Wave iddone left=0; } // if ==wave else { if(wave.getFCC()==MKFCCR('e','s','d','s')) { decodeEsds(&wave,TRACK_AUDIO); goto foundit; // FIXME!!! } else { printf("UNHANDLED ATOM : %s\n",fourCC::tostringBE(wave.getFCC())); } } } // if left > 10 foundit: // HACK FIXME left=0; } break; // mp4a } } break; default: ADM_assert(0); } son.skipBytes(left); } } break; default: printf("[STBL]Skipping atom %s\n",fourCC::tostringBE(son.getFCC())); } son.skipAtom(); } uint8_t r=0; uint32_t nbo=0; switch(trackType) { case TRACK_VIDEO: { if(_tracks[0].index) { printf("Already got a video track\n"); return 1; } r=indexify(&(_tracks[0]),trackScale,&info,0,&nbo); _videostream.dwLength= _mainaviheader.dwTotalFrames=_tracks[0].nbIndex; // update fps float f=_videostream.dwLength; if(_movieDuration) f=1000000.*f/_movieDuration; else f=25000; _videostream.dwRate=(uint32_t)floor(f); _mainaviheader.dwMicroSecPerFrame=ADM_UsecFromFps1000(_videostream.dwRate); // if we have a sync atom ??? if(info.nbSync) { // Mark keyframes for(int i=0;i<info.nbSync;i++) { int sync=info.Sync[i]; if(sync) sync--; _tracks[0].index[sync].intra=AVI_KEY_FRAME; } } else { // All frames are kf for(int i=0;i<_tracks[0].nbIndex;i++) { _tracks[0].index[i].intra=AVI_KEY_FRAME; } } // Now do the CTTS thing if(info.Ctts) { updateCtts(&info); } VDEO.index[0].intra=AVI_KEY_FRAME; } break; case TRACK_AUDIO: printf("Cur audio track :%u\n",nbAudioTrack); if(info.SzIndentical ==1 && (ADIO.encoding==WAV_LPCM || ADIO.encoding==WAV_PCM )) { printf("Overriding size %lu -> %lu\n", info.SzIndentical,info.SzIndentical*2*ADIO.channels); info.SzIndentical=info.SzIndentical*2*ADIO.channels; } r=indexify(&(_tracks[1+nbAudioTrack]),trackScale,&info,1,&nbo); printf("Indexed audio, nb blocks:%u\n",nbo); if(r) { nbo=_tracks[1+nbAudioTrack].nbIndex; if(nbo) _tracks[1+nbAudioTrack].nbIndex=nbo; else _tracks[1+nbAudioTrack].nbIndex=info.nbSz; printf("Indexed audio, nb blocks:%u (final)\n",_tracks[1+nbAudioTrack].nbIndex); _tracks[1+nbAudioTrack].scale=trackScale; nbAudioTrack++; } break; case TRACK_OTHER: r=1; break; } return r; }