//___________________________________ uint8_t A_SaveAudioNVideo(const char *name) { uint32_t needSmart=0,fl; GenericAviSave *nw=NULL; aviInfo info; uint8_t ret=0; video_body->getVideoInfo(&info); printf("\n video process mode : %d",videoProcessMode()); if (!videoProcessMode()) { if(video_body->isMultiSeg()) needSmart=1; video_body->getFlags(frameStart,&fl); if(!(fl&AVI_KEY_FRAME)) needSmart=1; if(needSmart) printf("\n probably need smart copy mode\n"); if( !isMpeg4Compatible( info.fcc) && !isMSMpeg4Compatible(info.fcc)) { printf("\n not encodable, cancelling smart mode\n"); needSmart=0; } int value=video_body->getEnv(ENV_EDITOR_SMART); nw=NULL; if(needSmart) { if(value) { nw=new GenericAviSaveSmart(3); } else { if(GUI_Question(QT_TR_NOOP("You may need smart copy.\n Enable it ?"))) { value=4; if( ! GUI_getIntegerValue(&value, 2, 31, "_Q factor (set 4):")) return 0; nw=new GenericAviSaveSmart(value); } } } if(!nw) nw=new GenericAviSaveCopy; } else { printf("\n Process mode\n"); nw=new GenericAviSaveProcess; } ret=nw->saveAvi(name); delete nw; return ret; }
uint8_t prepareDualPass(uint8_t *buffer,char *TwoPassLogFile,DIA_encoding *encoding_gui,Encoder *_encode,uint32_t total) { uint32_t len, flag; FILE *tmp; uint8_t reuse=0; ADMBitstream bitstream; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question(_("\n Reuse the existing log-file ?"))) { reuse=1; } } if(!reuse) { encoding_gui->setPhasis ("1st Pass"); aprintf("**Pass 1:%lu\n",total); _encode->startPass1 (); bitstream.data=buffer; for (uint32_t cf = 0; cf < total; cf++) { encoding_gui->setFrame (cf, total); if (!encoding_gui->isAlive()) { abt: GUI_Error_HIG (_("Aborting"), NULL); return 0; } bitstream.cleanup(cf); if (!_encode->encode (cf,&bitstream))// &len, buffer, &flag)) { printf("\n Encoding of frame %lu failed !\n",cf); return 0; } encoding_gui->setQuant(bitstream.out_quantizer); encoding_gui->feedFrame(bitstream.len); } encoding_gui->reset(); aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } encoding_gui->setPhasis ("2nd Pass"); return 1; }
int A_Save( char *name) { uint32_t end; // depending on the type we save a avi, a mpeg or a XVCD CodecFamilty family; family= videoCodecGetFamily(); // in case of copy mode, we stick to avi file format if(!videoProcessMode) family=CodecFamilyAVI; printf("**saving:**\n"); // Check if we need to do a sanity B frame check if(!videoProcessMode) { uint32_t pb; end=avifileinfo->nb_frames; // if the last frame is the last frame (!) // we add one to keep it, else we systematically skip // the last frame if(frameEnd==end-1) end=frameEnd+1; else end=frameEnd; if(!video_body->sanityCheckRef(frameStart,end,&pb)) { if(pb) { GUI_Alert("The video starts/ends by lonely B frame\nPlease remove them"); return 0; } if(!GUI_Question("Warning !\n Bframe has lost its reference frame\nContinue ?")) return 0; } } switch(family) { case CodecFamilyAVI: printf(" Avi family\n"); A_SaveAudioNVideo(name); break; case CodecFamilyMpeg: printf(" Mpeg family\n"); EncoderSaveMpeg(name); break; case CodecFamilyXVCD: printf(" Xvcd family\n"); oplug_mpegff(name); break; default: assert(0); return 0; } return 1; }
uint8_t DIA_encoding::isAlive( void ) { if(stopReq) { if(GUI_Question("Continue encoding, no will stop it ?")) { stopReq=0; } } if(!stopReq) return 1; return 0; }
uint8_t GUI_encoderIsAlive(void) { if(window&&( tobedestroyed==0)) return 1; // Ask if we are sure ? if(GUI_Question("Are you sure ?")==0) { if( tobedestroyed) { tobedestroyed=0; } else { GUI_encoderStart(); } return 1; } return 0; }
// CYB 2005.02.23: DND void fileReadWrite(SELFILE_CB *cb, int rw, char *name) { if(name) { if(cb) { FILE *fd; fd=fopen(name,"rb"); if(rw==0) // read { // try to open it.. if(!fd) { GUI_Error_HIG("File error", "Cannot open \"%s\".", name); return; } } else // write { if(fd) { fclose(fd); if(!GUI_Question("Overwrite file ?")) return; } // check we have right access to it fd=fopen(name,"wb"); if(!fd) { GUI_Error_HIG("Cannot write the file", "No write access to \"%s\".", name); return; } } fclose(fd); cb(name); ADM_dealloc(name); } // no callback -> return value } }
/** Load or append a file. The file type is determined automatically and the ad-hoc video decoder is spawned */ uint8_t ADM_Composer::addFile (char *name, uint8_t mode) { uint8_t ret = 0; aviInfo info; WAVHeader * _wavinfo; // aviHeader * tmp; fileType type = Unknown_FileType; UNUSED_ARG(mode); _haveMarkers=0; // by default no markers are present assert (_nb_segment < MAX_SEG); assert (_nb_video < MAX_VIDEO); if (!identify (name, &type)) return 0; #define OPEN_AS(x,y) case x:\ _videos[_nb_video]._aviheader=new y; \ ret = _videos[_nb_video]._aviheader->open(name); \ break; switch (type) { case VCodec_FileType: loadVideoCodecConf(name); return ADM_IGN; // we do it but it wil fail, no problem with that break; OPEN_AS (Mp4_FileType, mp4Header); OPEN_AS (H263_FileType, h263Header); // For AVI we first try top open it as openDML case AVI_FileType: _videos[_nb_video]._aviheader=new OpenDMLHeader; ret = _videos[_nb_video]._aviheader->open(name); break; OPEN_AS (Nuppel_FileType, nuvHeader); OPEN_AS (BMP_FileType, picHeader); OPEN_AS (MpegIdx_FileType, mpeg2decHeader); OPEN_AS (_3GPP_FileType, _3GPHeader); OPEN_AS (Ogg_FileType, oggHeader); case Mpeg_FileType: // look if the idx exists char tmpname[256]; assert(strlen(name)+5<256);; strcpy(tmpname,name); strcat(tmpname,".idx"); if(addFile(tmpname)) return 1; // then propose to index it if (GUI_Question ("This looks like mpeg\n Do you want to index it?")) { char * idx, * mname; int track; DIA_indexerPrefill(name); if (DIA_mpegIndexer (&mname, &idx, &track, 1)) { if ((mname == NULL) || (idx == NULL)) { GUI_Alert ("Select files!"); return 0; } printf ("\n indexing :%s to \n%s\n", mname, idx); if (indexMpeg (mname, idx, (uint8_t) track)) { printf("\n re-opening %s\n", idx); return addFile (idx, 0); } return 0; } } return 0; break; case WorkBench_FileType: return loadWorbench(name); default: if (type == Unknown_FileType) { printf ("\n not identified ...\n"); } else printf ("\n successfully identified but no loader support detected...\n"); return 0; } // check opening was successful if (ret == 0) { printf ("\n Attempt to open %s failed!\n", name); delete _videos[_nb_video]. _aviheader;; return 0; } // else update info _videos[_nb_video]._aviheader->getVideoInfo (&info); _videos[_nb_video]._aviheader->setMyName (name); // fourCC::print( info.fcc ); _total_frames += info.nb_frames; _videos[_nb_video]._nb_video_frames = info.nb_frames; // and update audio info //_________________________ _wavinfo = _videos[_nb_video]._aviheader->getAudioInfo (); //wavinfo); // will be null if no audio if (!_wavinfo) { printf ("\n *** NO AUDIO ***\n"); _videos[_nb_video]._audiostream = NULL; } else { _videos[_nb_video]._aviheader->getAudioStream (&_videos[_nb_video]. _audiostream); _videos[_nb_video]._audio_size = _videos[_nb_video]._audiostream->getLength (); // For mpeg2, try to guess if it is pulldowned material double duration_a, duration_v; double rdirect, rpulldown; duration_a=_videos[_nb_video]._audio_size; duration_a/=_wavinfo->byterate; // now we got duration in seconds // ditto for video duration_v= _videos[_nb_video]._nb_video_frames; duration_v/=info.fps1000; duration_v*=1000; printf("Audio : %f video : %f\n",duration_a,duration_v); if(MpegIdx_FileType==type && info.fps1000>29000 && info.fps1000<30000 && duration_a>1 && duration_v>1) { rdirect=(duration_a-duration_v)/duration_v; if(rdirect<0) rdirect=-rdirect; rpulldown=((duration_a*0.8)-duration_v)/duration_v; if(rpulldown<0) rpulldown=-rpulldown; printf("Direct : %f pd : %f\n",rdirect,rpulldown); if( rdirect*2> rpulldown) { printf("Probably pulldowned, switching to 23.976 \n"); AVIStreamHeader *ily = _videos[_nb_video]._aviheader-> getVideoStreamHeader (); ily->dwRate = 23976; ily->dwScale = 1000; } } } printf ("\n Decoder FCC: "); fourCC::print (info.fcc); // ugly hack if (info.fps1000 > 2000 * 1000) { printf (" FPS too high, switching to 25 fps hardcoded\n"); info.fps1000 = 25 * 1000; updateVideoInfo (&info); } uint32_t l; uint8_t * d; _videos[_nb_video]._aviheader->getExtraHeaderData (&l, &d); _videos[_nb_video].decoder = getDecoder (info.fcc, info.width, info.height, l, d); // // And automatically create the segment // _segments[_nb_segment]._reference = _nb_video; _segments[_nb_segment]._audio_size = _videos[_nb_video]._audio_size; _segments[_nb_segment]._audio_start = 0; _segments[_nb_segment]._start_frame = 0; _segments[_nb_segment]._nb_frames = _videos[_nb_video]._nb_video_frames ; _videos[_nb_video]._isAudioVbr=0; // next one please _nb_video++; _nb_segment++; //______________________________________ // 1- check for B _ frame existence // 2- check for consistency with reported flags //______________________________________ uint8_t count=0; TryAgain: _VIDEOS *vid; uint32_t err=0; vid= &(_videos[_nb_video-1]); vid->_forwardReference=0xFFFFFFF; vid->_forwardFrame= NULL; vid->_reorderReady=0; // we only try if we got everything needed... if(!vid->decoder) { printf("\n no decoder to check for B- frame\n"); return 1; } if(!vid->decoder->bFramePossible()) { printf("\n no B- frame with that codec \n"); return 1; } printf("\n checking for B-Frames...\n"); if( vid->_nb_video_frames >15) // 12 { uint8_t *buffer,*bufferin; uint32_t len,flags,flag2; uint8_t bframe=0, bconsistency=1; buffer=new uint8_t [info.width* info.height*2]; bufferin=new uint8_t [info.width* info.height*2]; // we decode 5 frames..should be enough to get an opinion for(uint32_t i=0;i<13;i++) //10 { flags=flag2=0; vid->_aviheader->getFrameNoAlloc (i, bufferin, &len, &flags); if(!vid->decoder->uncompress( (uint8_t *)bufferin,(uint8_t *)buffer,len,&flag2 )) { err++; printf("\n ***oops***\n"); } if(i<5) continue; // ignore the first frames // check if it is a b-frame //printf(" %lu : %lu \n",i,flag2); if(flag2 & AVI_B_FRAME) { printf(" %lu is a b frame\n",i); bframe=1; vid->_aviheader->getFlags(i,&flags); if(!(flags & AVI_B_FRAME)) bconsistency=0; else printf("\n and flags is ok\n"); } } delete [] buffer; delete [] bufferin; if(bframe) { printf("\n Mmm this appear to have b-frame...\n"); if(bconsistency) { printf("\n And the index is ok\n"); vid->_forwardFrame=new uint8_t [720*576*3]; vid->_reorderReady=vid->_aviheader->reorder(); if(vid->_reorderReady) { printf("\n Frames re-ordered, B-frame friendly now :)\n"); aprintf(" we had :%lu",info.nb_frames); // update nb frame in case we dropped some _total_frames -= info.nb_frames; _videos[_nb_video-1]._aviheader->getVideoInfo (&info); aprintf(" we have now :%lu",info.nb_frames); _total_frames += info.nb_frames; _videos[_nb_video-1]._nb_video_frames = info.nb_frames; } else { printf("\n Frames not re-ordered, expect problem with b-frames\n"); } } else { printf("\n But the index is not up to date \n"); uint32_t ispacked=0; // If it is Divx 5.0.xxx use divx decoder if(fourCC::check(info.fcc,(uint8_t *)"DX50") || fourCC::check(info.fcc,(uint8_t *)"XVID" )) { //if(vid->decoder->isDivxPacked()) if(vid->decoder->isDivxPacked()) { // can only unpack avi if(!count && type==AVI_FileType) { if(GUI_Question("It looks like Vop packed divx.\nDo you want me to unpack it ?")) { OpenDMLHeader *dml=NULL; count++; dml=(OpenDMLHeader *)vid->_aviheader; // Can we repack it ? if(dml->unpackPacked()) goto TryAgain; GUI_Alert("Could not unpack it\n, using backup decoder= not frame accurate."); } } #if 1 //def USE_DIVX printf("\n Switching codec...\n"); delete vid->decoder; vid->decoder=getDecoderVopPacked(info.fcc, info.width, info.height,0,NULL); ispacked=1; #else GUI_Alert("Troubles ahead : This a vop packed avi.."); #endif } } // else warn user if(!ispacked) GUI_Alert("\n Please used Misc->Rebuild frame for BFrames!"); } } else { printf("Seems it does not contain B-frames...\n"); } printf(" End of B-frame check\n"); } return 1; }
void FileSel_ReadWrite(SELFILE_CB *cb, int rw, const char *name, const char *actual_workbench_file) { if(name) { if(cb) { FILE *fd; fd=ADM_fopen(name,"rb"); if(rw==0) // read { // try to open it.. if(!fd) { GUI_Error_HIG(QT_TRANSLATE_NOOP("filesel","File error"), QT_TRANSLATE_NOOP("filesel","Cannot open \"%s\"."), name); return; } } else // write { if(fd){ struct stat buf; int fdino; ADM_fclose(fd); char msg[300]; snprintf(msg, 300, QT_TRANSLATE_NOOP("filesel","%s already exists.\n\nDo you want to replace it?"), ADM_GetFileName(name)); if(!GUI_Question(msg)) return; /* ** JSC Fri Feb 10 00:07:30 CET 2006 ** compare existing output file inode against each current open files inode ** i'm ignoring st_dev, so we may get false positives ** i'm testing until fd=1024, should be MAXFD computed by configure ** keep in mind: ** you can overwrite .idx files, they are loaded into memory and closed soon ** you cannot overwrite segment data files, all files are kept open and ** are detected here */ #ifndef _WIN32 if( stat(name,&buf) == -1 ){ fprintf(stderr,"stat(%s) failed\n",name); return; } #endif fdino = buf.st_ino; for(int i=0;i<1024;i++){ if( fstat(i,&buf) != -1 ){ if( buf.st_ino == fdino ){ char str[512]; snprintf(str,512,"File \"%s\" exists and is opened by Avidemux",name); GUI_Error_HIG(str, QT_TRANSLATE_NOOP("filesel","It is possible that you are trying to overwrite an input file!")); return; } } } /* ** compare output file against actual EMCAscript file ** need to stat() to avoid symlink (/home/x.js) vs. real file (/export/home/x.js) case */ if( actual_workbench_file ){ if( stat(actual_workbench_file,&buf) != -1 ){ if( buf.st_ino == fdino ){ char str[512]; snprintf(str,512,"File \"%s\" exists and is the actual ECMAscript file",name); GUI_Error_HIG(str,QT_TRANSLATE_NOOP("filesel","It is possible that you are trying to overwrite an input file!")); return; } } } } // check we have right access to it fd=ADM_fopen(name,"wb"); if(!fd) { GUI_Error_HIG(QT_TRANSLATE_NOOP("filesel","Cannot write the file"),QT_TRANSLATE_NOOP("filesel", "No write access to \"%s\"."), name); return; } } ADM_fclose(fd); cb(name); } // no callback -> return value } }
void GUI_FileSel(const char *label, SELFILE_CB * cb, int rw,char **rname) { /* Create the selector */ GtkWidget *dialog; char *name=NULL; char *tmpname; gchar *selected_filename; if(rname) *rname=NULL; dialog=create_fileselection1(); gtk_window_set_title (GTK_WINDOW (dialog),label); gtk_transient(dialog); if( prefs->get(LASTDIR,&tmpname)) { // printf("tmpname : %s\n",tmpname); char *str=PathCanonize(tmpname); // printf("tmpname : %s\n",str); PathStripName(str); // printf("tmpname : *%s*\n",str); gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog),(gchar *)str); delete [] str; } if(gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_OK) { selected_filename= (gchar *) gtk_file_selection_get_filename(GTK_FILE_SELECTION(dialog)); if (*(selected_filename + strlen(selected_filename) - 1) == '/') GUI_Alert("Cannot open directory as file !"); else { name=strdup(selected_filename); char *str=PathCanonize(name); PathStripName(str); prefs->set(LASTDIR,str); delete [] str; } } gtk_widget_destroy(dialog); if(name) { if(cb) { if(rw==0) // read { // try to open it.. FILE *fd; fd=fopen(name,"rb"); if(!fd) { GUI_Alert("Cannot open this file !"); return; } fclose(fd); cb(name); free(name); } else // write { FILE *fd; fd=fopen(name,"rb"); if(fd) { fclose(fd); if(!GUI_Question("Overwrite file ?")) return; } // check we have right access to it fd=fopen(name,"wb"); if(!fd) { GUI_Alert("No write access to that file !"); return; } fclose(fd); cb(name); free(name); } } // no callback -> return value else { *rname=name; } } }
/** \fn runH264 \brief Index H264 stream */ bool TsIndexer::runH264(const char *file,ADM_TS_TRACK *videoTrac) { bool seq_found=false; bool firstSps=true; TSVideo video; indexerData data; dmxPacketInfo tmpInfo; TS_PESpacket SEI_nal(0); bool result=false; bool bAppend=false; beginConsuming=0; listOfUnits.clear(); printf("Starting H264 indexer\n"); if(!videoTrac) return false; if(videoTrac[0].trackType!=ADM_TS_H264) { printf("[Ts Indexer] Only H264 video supported\n"); return false; } video.pid=videoTrac[0].trackPid; memset(&data,0,sizeof(data)); data.picStructure=pictureFrame; string indexName=string(file); indexName=indexName+string(".idx2"); index=qfopen(indexName,(const char*)"wt"); if(!index) { printf("[PsIndex] Cannot create %s\n",indexName.c_str()); return false; } pkt=new tsPacketLinearTracker(videoTrac->trackPid, audioTracks); FP_TYPE append=FP_DONT_APPEND; if(true==ADM_probeSequencedFile(file)) { if(true==GUI_Question("There are several files with sequential file names. Should they be all loaded ?")) bAppend=true; } if(bAppend==true) append=FP_APPEND; writeSystem(file,bAppend); pkt->open(file,append); data.pkt=pkt; fullSize=pkt->getSize(); gui=createProcessing("Indexing",pkt->getSize()); int lastRefIdc=0; bool keepRunning=true; //****************** // 1 search SPS //****************** while(keepRunning) { int startCode=pkt->findStartCode(); if(startCode&0x80) continue; // Marker missing startCode&=0x1f; if(startCode!=NAL_SPS) continue; // Got SPS! uint32_t xA,xR; // Get info pkt->getInfo(&tmpInfo); // Read just enough... { SEI_nal.empty(); uint32_t code=0xffff+0xffff0000; while(((code&0xffffff)!=1) && pkt->stillOk()) { uint8_t r=pkt->readi8(); code=(code<<8)+r; SEI_nal.pushByte(r); } if(!pkt->stillOk()) break;; pkt->seek(tmpInfo.startAt,tmpInfo.offset-5); if (extractSPSInfo(SEI_nal.payload, SEI_nal.payloadSize-4,&spsInfo)) { ADM_info("[TsIndexer] Found video %"PRIu32"x%"PRIu32", fps=%"PRIu32"\n",video.w,video.h,video.fps); ADM_info("[TsIndexer] SPS says %"PRIu32"x%"PRIu32"\n",spsInfo.width,spsInfo.height); seq_found=1; video.w=spsInfo.width; video.h=spsInfo.height; video.fps=spsInfo.fps1000; xA=spsInfo.darNum; xR=spsInfo.darDen; writeVideo(&video,ADM_TS_H264); writeAudio(); qfprintf(index,"[Data]"); // Rewind break; }; } } if(!seq_found) goto the_end; decodingImage=false; //****************** // 2 Index //****************** bool fourBytes; while(keepRunning) { fourBytes=false; int startCode=pkt->findStartCode2(fourBytes); resume: if(!pkt->stillOk()) break; int startCodeLength=4; if(fourBytes==true) startCodeLength++; // 1:0 2:Nal ref idc 5:Nal Type if(startCode&0x80) { printf("[Ts] Nal Marker missing:%x\n",startCode); continue; // Marker missing } int fullStartCode=startCode; int ref=(startCode>>5)&3; startCode&=0x1f; // Ignore nal ref IDR aprintf("[%02x] Nal :0x%x,ref=%d,lastRef=%d at : %d \n",fullStartCode,startCode,ref,lastRefIdc,pkt->getConsumed()-beginConsuming); // Ignore multiple chunk of the same pic if((startCode==NAL_NON_IDR || startCode==NAL_IDR)&&decodingImage ) { aprintf("Still capturing, ignore\n"); continue; } switch(startCode) { case NAL_AU_DELIMITER: { aprintf("AU DELIMITER\n"); decodingImage = false; } break; case NAL_SEI: { // Load the whole NAL SEI_nal.empty(); uint32_t code=0xffff+0xffff0000; while(((0xffffff&code)!=1) && pkt->stillOk()) { uint8_t r=pkt->readi8(); code=(code<<8)+r; SEI_nal.pushByte(r); } if(!pkt->stillOk()) goto resume; aprintf("[SEI] Nal size :%d\n",SEI_nal.payloadSize); if(SEI_nal.payloadSize>=7) decodeSEI(SEI_nal.payloadSize-4, SEI_nal.payload,&(thisUnit.recoveryCount),&(thisUnit.imageStructure)); else printf("[SEI] Too short size+4=%d\n",*(SEI_nal.payload)); startCode=pkt->readi8(); decodingImage=false; pkt->getInfo(&thisUnit.packetInfo); thisUnit.consumedSoFar=pkt->getConsumed(); if(!addUnit(data,unitTypeSei,thisUnit,startCodeLength+SEI_nal.payloadSize+1)) keepRunning=false; fourBytes=true; goto resume; } break; case NAL_SPS: decodingImage=false; pkt->getInfo(&thisUnit.packetInfo); if(firstSps) { pkt->setConsumed(startCodeLength); // reset consume counter firstSps=false; } thisUnit.consumedSoFar=pkt->getConsumed(); if(!addUnit(data,unitTypeSps,thisUnit,startCodeLength)) keepRunning=false; break; case NAL_IDR: case NAL_NON_IDR: { #define NON_IDR_PRE_READ 8 aprintf("Pic start last ref:%d cur ref:%d nb=%d\n",lastRefIdc,ref,data.nbPics); lastRefIdc=ref; uint8_t bufr[NON_IDR_PRE_READ+4]; uint8_t header[NON_IDR_PRE_READ+4]; pkt->read(NON_IDR_PRE_READ,bufr); // unescape... ADM_unescapeH264(NON_IDR_PRE_READ,bufr,header); // getBits bits(NON_IDR_PRE_READ,header); int first_mb_in_slice,slice_type; first_mb_in_slice= bits.getUEG(); slice_type= bits.getUEG31(); if(slice_type>9) { printf("[TsIndexer] Bad slice type\n"); } if(slice_type>4) slice_type-=5; switch(slice_type) { case 0 : thisUnit.imageType=2;break; // P case 1 : thisUnit.imageType=3;break; // B case 2 : thisUnit.imageType=1;break; // I default : thisUnit.imageType=2;break; // SP/SI } if(startCode==NAL_IDR) thisUnit.imageType=4; // IDR aprintf("[>>>>>>>>] Pic Type %"PRIu32" Recovery %"PRIu32"\n",thisUnit.imageType,recoveryCount); if(thisUnit.imageType==1 && !thisUnit.recoveryCount) thisUnit.imageType=4; //I + Recovery=0 = IDR! data.nbPics++; decodingImage=true; pkt->getInfo(&thisUnit.packetInfo); thisUnit.consumedSoFar=pkt->getConsumed(); if(!addUnit(data,unitTypePic,thisUnit,startCodeLength+NON_IDR_PRE_READ)) keepRunning=false; // reset to default thisUnit.imageStructure=pictureFrame; thisUnit.recoveryCount=0xff; pkt->invalidatePtsDts(); } break; default: break; } } // End while result=true; the_end: printf("\n"); qfprintf(index,"\n[End]\n"); qfclose(index); index=NULL; audioTracks=NULL; delete pkt; pkt=NULL; return result; }
/*-------------------------------------------------------------------------------------------------------------------*/ uint8_t mpegWritter::save_dualpass(char *name,uint32_t final_size,uint32_t bitrate,ADM_MPEGTYPE mpegtype, int matrix,uint8_t interlaced, uint8_t bff, // WLA uint8_t widescreen) { AVDMGenericVideoStream *incoming; char *statname; incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); _w=incoming->getInfo()->width; _h=incoming->getInfo()->height; _page=_w*_h; _page+=_page>>1; _fps1000=incoming->getInfo()->fps1000; _total=incoming->getInfo()->nb_frames; if(!_total) return 0; _buffer =new uint8_t[_w*_h*2]; _buffer_out=new uint8_t[_w*_h*2]; statname=new char[strlen(name)+4+1]; strcpy(statname,name); strcat(statname,".st"); printf("Matrix : %d\n\n",matrix); encoding=new DIA_encoding(_fps1000); encoding->setPhasis("Encoding"); // check if stat file exists ? FILE *fd; uint8_t reuse=0; fd=fopen(statname,"rt"); if(fd) { fclose(fd); if(GUI_Question("Reuse log file ?")) reuse=1; } #if 1 if(!reuse) // if(!dopass1(name,statname,final_size,bitrate,mpegtype,matrix,interlaced,widescreen)) if(!dopass1(name,statname,final_size,bitrate,mpegtype,matrix,interlaced,bff,widescreen)) // WLA { delete encoding; GUI_Alert("Error in pass 1"); delete [] statname; return 0; } #endif // if(!dopass2(name,statname,final_size,bitrate,mpegtype,matrix,interlaced,widescreen)) if(!dopass2(name,statname,final_size,bitrate,mpegtype,matrix,interlaced,bff,widescreen)) // WLA { delete encoding; GUI_Alert("Error in pass 2"); delete [] statname; return 0; } delete encoding; delete [] statname; return 1; }
//______________________________________ // // 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; }
/** \fn GUI_FileSelWrite (const char *label, char **name, uint32_t access) \brief Ask for a file for reading (access=0) or writing (access=1) */ static void GUI_FileSelSelectWriteInternal(const char *label, const char *ext, char **name) { *name = NULL; QString str ; QString fileName,dot=QString("."); QString filterFile=QString(QT_TRANSLATE_NOOP("qfile","All files (*.*)")); bool doFilter = !!(ext && strlen(ext)); QFileDialog::Options opts; int extSize=1; if(doFilter) { extSize+=strlen(ext); } //printf("Do filer=%d\n",(int)doFilter); std::string lastFolder; admCoreUtils::getLastWriteFolder(lastFolder); if (lastFolder.size()) { QString outputPath = QFileInfo(QString::fromUtf8(lastFolder.c_str())).path(); char *tmpinputname = NULL; QString inputBaseName = QString(""); std::string lastRead; admCoreUtils::getLastReadFolder(lastRead); if (lastRead.size()) { inputBaseName = QFileInfo(QString::fromUtf8(lastRead.c_str())).completeBaseName(); } QString outputExt = QString(""); if (doFilter) { outputExt = dot+QString(ext); } QString separator = QString("/"); str = outputPath+separator+inputBaseName+outputExt; /* LASTDIR may have gone; then do nothing and use current dir instead (implied) */ if (!QDir(outputPath).exists()) str.clear(); } if(doFilter) { filterFile=QString(ext)+QString(QT_TRANSLATE_NOOP("qfile"," files (*."))+QString(ext)+QString(");;")+filterFile; } fileName = QFileDialog::getSaveFileName(NULL, label, // caption str, // folder filterFile, // filter NULL,QFileDialog::DontConfirmOverwrite); // selected filter if (fileName.isNull() ) return; *name=(char *)ADM_alloc( strlen(fileName.toUtf8().constData())+extSize); strcpy(*name,fileName.toUtf8().constData()); // Check if we need to add an extension.... if(doFilter) { if(!strstr(*name,".")) { strcat(*name,"."); strcat(*name,ext); fileName=fileName+QString(".")+QString(ext); } } QFile newFile(fileName); if(newFile.exists()) { QFileInfo fileInfo(newFile); QString q=QString(QT_TRANSLATE_NOOP("qfile","Overwrite file "))+fileInfo.fileName()+QString("?"); if(!GUI_Question(q.toUtf8().constData())) { ADM_dezalloc(*name); *name=NULL; return; } } admCoreUtils::setLastWriteFolder( std::string(fileName.toUtf8().constData())); }
/*-------------------------------------------------------------------------------------------------------------------*/ uint8_t mpegWritter::save_dualpass (const char *name, uint32_t final_size, uint32_t bitrate, ADM_MPEGTYPE mpegtype, int matrix, uint8_t interlaced, uint8_t bff, // WLA uint8_t widescreen) { AVDMGenericVideoStream *incoming; char *statname; uint32_t reuse = 0; incoming = getLastVideoFilter (frameStart, frameEnd - frameStart); _w = incoming->getInfo ()->width; _h = incoming->getInfo ()->height; _page = _w * _h; _page += _page >> 1; _fps1000 = incoming->getInfo ()->fps1000; _total = incoming->getInfo ()->nb_frames; if (!_total) return 0; //_buffer =new uint8_t[_w*_h*2]; aImage = new ADMImage (_w, _h); _buffer_out = new uint8_t[_w * _h * 2]; statname = new char[strlen (name) + 4 + 1]; strcpy (statname, name); strcat (statname, ".st"); printf ("Matrix : %d\n\n", matrix); encoding = new DIA_encoding (_fps1000); encoding->setPhasis ("Encoding"); // check if stat file exists ? #if 1 //ndef CYG_MANGLING { FILE *fd; fd = fopen (statname, "rt"); if (fd) { fclose (fd); prefs->get (FEATURE_REUSE_2PASS_LOG, (uint32_t *) & reuse); if (!reuse && GUI_Question (_("Reuse log file ?"))) reuse = 1; } } #endif //_ratecontrol=new ADM_oldXvidRc(_fps1000,statname); _ratecontrol = new ADM_newXvidRc (_fps1000, statname); #if 1 if (!reuse) // if(!dopass1(name,statname,final_size,bitrate,mpegtype,matrix,interlaced,widescreen)) if (!dopass1 (name, statname, final_size, bitrate, mpegtype, matrix, interlaced, bff, widescreen)) // WLA { delete encoding; GUI_Error_HIG (_("Error in pass 1"), NULL); delete[]statname; return 0; } #endif // if(!dopass2(name,statname,final_size,bitrate,mpegtype,matrix,interlaced,widescreen)) if (!dopass2 (name, statname, final_size, bitrate, mpegtype, matrix, interlaced, bff, widescreen)) // WLA { delete encoding; GUI_Error_HIG (_("Error in pass 2"), NULL); delete[]statname; return 0; } delete encoding; delete[]statname; return 1; }
bool admSaver::save(void) { int ret=false; ADM_info("Audio starting time %s\n",ADM_us2plain(startAudioTime)); ADM_info("[A_Save] Saving..\n"); const char *defaultExtension=ADM_MuxerGetDefaultExtension(muxerIndex); EditableAudioTrack *ed=NULL; ADM_info("Muxer default extension %s\n",defaultExtension); if(!videoEncoderIndex) { if(false==video_body-> checkCutsAreOnIntra()) { if(!GUI_Question("The video is in copy mode but the cut points are not on keyframes.\n" "The video will be saved but there will corruption at cut point(s).\n" "Do you want to continue anyway ?")) { return false; } } } if(!(muxer=ADM_MuxerSpawnFromIndex(muxerIndex))) { GUI_Error_HIG("Muxer","Cannot instantiante muxer"); return 0; } ADM_videoStream *video=setupVideo(); if(!video) { return false; } // adjust audio starting time for(int i=0;i<nbAudioTracks;i++) { ADM_audioStream *stream=video_body->getAudioStreamAt(i); stream->goToTime(startAudioTime); } if(false==setupAudio()) { if(video) delete video; if(muxer) delete muxer; muxer=NULL; return false; } // Check if we need to add an extension.... if(defaultExtension) { if(!strstr(fileName.c_str(),".")) { fileName=fileName+std::string(".")+std::string(defaultExtension); ADM_info("Adding extension, filename is now %s\n",fileName.c_str()); } } if(!muxer->open(fileName.c_str(),video,nbAudioTracks,audioAccess)) { GUI_Error_HIG("Muxer","Cannot open "); }else { ret=muxer->save(); muxer->close(); } abort123: if(video) delete video; video=NULL; for(int i=0;i<nbAudioTracks;i++) { delete audioAccess[i]; audioAccess[i]=NULL; } return ret; }
uint8_t oplug_mpegff(const char *name, ADM_OUT_FORMAT type) { AVDMGenericVideoStream *_incoming; Encoder *encoder=NULL; ADMMpegMuxer *muxer=NULL; FILE *file=NULL; uint8_t audioBuffer[48000]; uint32_t audioLen=0; uint32_t _w,_h,_fps1000,_page,total; AVDMGenericAudioStream *audio=NULL; uint32_t len,flags; uint32_t size; ADM_MUXER_TYPE mux; uint32_t audio_encoding=0; uint32_t real_framenum=0; uint8_t ret=0; uint32_t sample_target=0; uint32_t total_sample=0; ADMBitstream bitstream(0); uint32_t audioSum=0; DIA_encoding *encoding; int reuse = 0; twoPass=new char[strlen(name)+6]; twoFake=new char[strlen(name)+6]; strcpy(twoPass,name); strcat(twoPass,".stat"); strcpy(twoFake,name); strcat(twoFake,".fake"); _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); _w=_incoming->getInfo()->width; _h=_incoming->getInfo()->height; _fps1000=_incoming->getInfo()->fps1000; _page=_w*_h; _page+=_page>>1; total=_incoming->getInfo()->nb_frames; if(!total) return 0; switch(type) { default: ADM_assert(0); case ADM_ES: // Else open file (if possible) mux=MUXER_NONE; break; case ADM_TS: if(!currentaudiostream) { GUI_Error_HIG(QT_TR_NOOP("There is no audio track"), NULL); goto finishvcdff; } audio=mpt_getAudioStream(); mux=MUXER_TS; break; case ADM_PS: { if(!currentaudiostream) { GUI_Error_HIG(QT_TR_NOOP("There is no audio track"), NULL); goto finishvcdff; } audio=mpt_getAudioStream(); // Have to check the type // If it is mpeg2 we use DVD-PS // If it is mpeg1 we use VCD-PS // Later check if it is SVCD if(!audio) { GUI_Error_HIG(QT_TR_NOOP("Audio track is not suitable"), NULL); goto finishvcdff; } // Check WAVHeader *hdr=audio->getInfo(); audio_encoding=hdr->encoding; if (videoCodecGetType() == CodecXVCD || videoCodecGetType() == CodecVCD) { if(hdr->frequency!=44100 || hdr->encoding != WAV_MP2) { GUI_Error_HIG(("Incompatible audio"),QT_TR_NOOP( "For VCD, audio must be 44.1 kHz MP2.")); goto finishvcdff; } mux=MUXER_VCD; printf("X*CD: Using VCD PS\n"); }else { aviInfo info; video_body->getVideoInfo(&info); if(hdr->frequency==44100 && _w==480&&hdr->encoding == WAV_MP2 ) // SVCD ? { mux=MUXER_SVCD; printf("X*VCD: Using SVCD PS\n"); } else { // mpeg2, we do only DVD right now if(hdr->frequency!=48000 || (hdr->encoding != WAV_MP2 && hdr->encoding!=WAV_AC3 && hdr->encoding!=WAV_LPCM)) { GUI_Error_HIG(QT_TR_NOOP("Incompatible audio"), QT_TR_NOOP("For DVD, audio must be 48 kHz MP2, AC3 or LPCM.")); goto finishvcdff; } mux=MUXER_DVD; printf("X*VCD: Using DVD PS\n"); } } } } // Create muxer switch (videoCodecGetType()) { case CodecXVCD: encoder=new EncoderFFMPEGMpeg1(FF_MPEG1,&ffmpeg1Codec); printf("\n Using ffmpeg mpeg1 encoder\n"); break; case CodecXSVCD: encoder=new EncoderFFMPEGMpeg1(FF_MPEG2,&ffmpeg2SVCDCodec); printf("\n Using ffmpeg mpeg2 encoder\n"); break; case CodecXDVD: encoder=new EncoderFFMPEGMpeg1(FF_MPEG2,&ffmpeg2DVDCodec); printf("\n Using ffmpeg mpeg2 encoder (DVD)\n"); break; case CodecDVD: encoder=new EncoderMpeg2enc(MPEG2ENC_DVD,&DVDCodec); printf("\n Using mpeg2enc encoder (DVD)\n"); break; case CodecRequant: if(!isMpeg12Compatible(avifileinfo->fcc)) { GUI_Error_HIG("Incompatible Input","The input file must be mpeg2 to be able to use requant!"); return 0; // Fixme, do some cleanup } encoder=new EncoderRequant(&RequantCodec); printf("\n Using mpeg2 requant\n"); break; break; case CodecSVCD: encoder=new EncoderMpeg2enc(MPEG2ENC_SVCD,&SVCDCodec); printf("\n Using mpeg2enc encoder (SVCD)\n"); break; case CodecVCD: encoder=new EncoderMpeg2enc(MPEG2ENC_VCD,&VCDCodec); printf("\n Using mpeg2enc encoder (VCD)\n"); break; default: ADM_assert(0); } encoder->setLogFile(twoPass,total); if (encoder->isDualPass()) { printf("Verifying log file\n"); if (encoder->verifyLog(twoPass, total) && GUI_Question(QT_TR_NOOP("Reuse the existing log file?"))) reuse = 1; } if(!encoder->configure(_incoming, reuse)) goto finishvcdff; _buffer=new uint8_t[_page]; // Might overflow if _page only _outbuffer=new uint8_t[_page]; ADM_assert( _buffer); ADM_assert( _outbuffer); encoding =new DIA_encoding(_fps1000); switch (videoCodecGetType()) { case CodecVCD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc VCD")); break; case CodecSVCD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc SVCD")); break; case CodecDVD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc DVD")); break; case CodecXVCD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-1 VBR")); break; case CodecXSVCD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-2 SVCD VBR")); break; case CodecXDVD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-2 DVD VBR")); break; case CodecRequant: encoding->setCodec(QT_TR_NOOP("MPEG Requantizer")); break; default: ADM_assert(0); } switch(mux) { case MUXER_NONE:encoding->setContainer(QT_TR_NOOP("MPEG ES"));break; case MUXER_TS: encoding->setContainer(QT_TR_NOOP("MPEG TS"));break; case MUXER_VCD: encoding->setContainer(QT_TR_NOOP("MPEG VCD"));break; case MUXER_SVCD:encoding->setContainer(QT_TR_NOOP("MPEG SVCD"));break; case MUXER_DVD: encoding->setContainer(QT_TR_NOOP("MPEG DVD"));break; default: ADM_assert(0); } // pass 1 if(encoder->isDualPass()) //Cannot be requant { if(!reuse) { encoding->setPhasis (QT_TR_NOOP("Pass 1/2")); encoder->startPass1(); bitstream.data=_buffer; bitstream.bufferSize=_page; for(uint32_t i=0;i<total;i++) { bitstream.cleanup(i); if(!encoder->encode( i, &bitstream))//&len,(uint8_t *) _buffer,&flags)) { GUI_Error_HIG(QT_TR_NOOP("Error in pass 1"), NULL); } encoding->setFrame(i,bitstream.len,bitstream.out_quantizer,total); if(!encoding->isAlive()) goto finishvcdff; } } encoder->startPass2(); encoding->reset(); } switch(type) { case ADM_PS: muxer=new mplexMuxer; break; case ADM_TS: muxer=new tsMuxer; break; case ADM_ES: break; default: ADM_assert(0); } if(muxer) { if(!muxer->open(name,0,mux,avifileinfo,audio->getInfo())) { printf("Muxer init failed\n"); goto finishvcdff; } double sample_time; sample_time=total; sample_time*=1000; sample_time/=_fps1000; // target_time in second sample_time*=audio->getInfo()->frequency; sample_target=(uint32_t)floor(sample_time); } else { file=fopen(name,"wb"); if(!file) { GUI_Error_HIG(QT_TR_NOOP("File error"), QT_TR_NOOP("Cannot open \"%s\" for writing."), name); goto finishvcdff; } } if(encoder->isDualPass()) encoding->setPhasis (QT_TR_NOOP("Pass 2/2")); else encoding->setPhasis (QT_TR_NOOP("Encoding")); // Set info for audio if any if(muxer) { if(!audioProcessMode()) encoding->setAudioCodec(QT_TR_NOOP("Copy")); else encoding->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); } //********************************************************** // In that case we do multithreadedwriting (yes!) //********************************************************** if(mux==MUXER_DVD || mux==MUXER_SVCD || mux==MUXER_VCD) { pthread_t audioThread,videoThread,muxerThread; muxerMT context; // bitstream.data=_outbuffer; bitstream.bufferSize=_page; // memset(&context,0,sizeof(context)); context.videoEncoder=encoder; context.audioEncoder=audio; context.muxer=(mplexMuxer *)muxer; context.nbVideoFrame=total; context.audioTargetSample=sample_target; context.audioBuffer=audioBuffer; context.bitstream=&bitstream; context.opaque=(void *)encoding; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioSlave,&context)); ADM_assert(!pthread_create(&videoThread,NULL,(THRINP)defaultVideoSlave,&context)); while(1) { accessMutex.lock(); if(!encoding->isAlive()) { context.audioAbort=1; context.videoAbort=1; printf("[mpegFF]Waiting for slaves\n"); accessMutex.unlock(); while(1) { accessMutex.lock(); if(context.audioDone && context.videoDone) { printf("[mpegFF]Both audio & video done\n"); if(context.audioDone==1 && context.videoDone==1) ret=1; accessMutex.unlock(); goto finishvcdff; } accessMutex.unlock(); ADM_usleep(50000); } } if(context.audioDone==2 || context.videoDone==2 ) //ERROR { context.audioAbort=1; context.videoAbort=1; } if(context.audioDone && context.videoDone) { printf("[mpegFF]Both audio & video done\n"); if(context.audioDone==1 && context.videoDone==1) ret=1; accessMutex.unlock(); goto finishvcdff; } accessMutex.unlock(); ADM_usleep(1000*1000); } } //********************************************************** // NOT MULTITHREADED //********************************************************** bitstream.data=_outbuffer; bitstream.bufferSize=_page; for(uint32_t i=0;i<total;i++) { // get frame bitstream.cleanup(i); if(!encoder->encode( i,&bitstream))// &len,(uint8_t *) _outbuffer,&flags)) { GUI_Error_HIG(QT_TR_NOOP("Error in pass 2"), NULL); goto finishvcdff; } if(!bitstream.len) continue; if(file) { fwrite(_outbuffer,bitstream.len,1,file); } else { uint32_t samples; //printf("%lu %lu\n",i,dts); muxer->writeVideoPacket(&bitstream); real_framenum++; // _muxer->writeVideoPacket(len,_buffer_out, //i-MPEG_PREFILL,_codec->getCodedPictureNumber()); if(total_sample<sample_target) { while(muxer->needAudio() && total_sample<sample_target) { if(!audio->getPacket(audioBuffer, &audioLen, &samples)) { break; } if(audioLen) { muxer->writeAudioPacket(audioLen,audioBuffer); total_sample+=samples; audioSum+=audioLen; } } } } encoding->setFrame(i,bitstream.len,bitstream.out_quantizer,total); encoding->setAudioSize(audioSum); if(!encoding->isAlive ()) goto finishvcdff; } ret=1; finishvcdff: printf("[MPEGFF] Finishing..\n"); delete encoding; end(); if(file) { fclose(file); file=NULL; } else if(muxer) { muxer->close(); delete muxer; muxer=NULL; } delete encoder; if (audio) deleteAudioFilter(audio); return ret; }
ReplyType glyphToText(admGlyph *glyph,admGlyph *head,char *decodedString) { admGlyph *cand; //printf("2t: %d x %d\n",glyph->width,glyph->height); if(glyph->width<2 && glyph->height<2) { delete glyph; return ReplyOk; } cand=searchGlyph(head,glyph); if(!cand) // New glyph { char *string; // Draw it displaySmall(glyph); gtk_label_set_text(GTK_LABEL(WID(labelText)),decodedString); gtk_editable_delete_text(GTK_EDITABLE(WID(entry)), 0,-1); //gtk_widget_set_sensitive(WID(buttonAccept),1); //gtk_widget_set_sensitive(WID(buttonSkip),1); //gtk_widget_set_sensitive(WID(entryEntry),1); gtk_widget_grab_focus (WID(entry)); gtk_widget_grab_default (WID(buttonOk)); //printf("i\n"); switch(gtk_dialog_run(GTK_DIALOG(dialog))) { case actionIgnore: glyph->code=NULL; insertInGlyphTree(head,glyph); //*nbGl++; break; case actionCalibrate: return ReplyCalibrate; case actionAccept: string =gtk_editable_get_chars(GTK_EDITABLE (WID(entry)), 0, -1); if(string&& strlen(string)) { glyph->code=ADM_strdup(string); insertInGlyphTree(head,glyph); //printf("New glyph:%s\n",glyph->code); strcat(decodedString,glyph->code); //*nbGl++; } else delete glyph; break; case actionSkip: //SKIP return ReplySkip; break; case actionSkipAll: return ReplySkipAll; break; case GTK_RESPONSE_CLOSE: if(GUI_Question(QT_TR_NOOP("Sure ?"))) return ReplyClose; break; // Abort } gtk_editable_delete_text(GTK_EDITABLE(WID(entry)), 0,-1); //gtk_widget_set_sensitive(WID(buttonAccept),0); //gtk_widget_set_sensitive(WID(buttonSkip),0); //gtk_widget_set_sensitive(WID(entryEntry),0); } else { //printf("Glyph known :%s \n",cand->code); if(cand->code) strcat(decodedString,cand->code); delete glyph; } return ReplyOk; }
uint8_t GenericAviSaveProcess::setupVideo (char *name) { _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); frametogo=_incoming->getInfo()->nb_frames; encoding_gui->setFps(_incoming->getInfo()->fps1000); // anish if(_incoming->getInfo()->width%8) { if(!GUI_Question(QT_TR_NOOP("Width is not a multiple of 8\n continue anyway ?"))) return 0; } _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height); if (!_encode) return 0; // init compressor TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,frametogo); int reuse = 0; if (_encode->isDualPass()) { FILE *tmp; if ((tmp = fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if (GUI_Question(QT_TR_NOOP("Reuse the existing log file?"))) reuse = 1; } } if (!_encode->configure (_incoming, reuse)) { delete _encode; _encode = NULL; GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL); return 0; }; memcpy (&_bih, video_body->getBIH (), sizeof (_bih)); _bih.biWidth = _incoming->getInfo ()->width; _bih.biHeight = _incoming->getInfo ()->height; _bih.biSize=sizeof(_bih); _bih.biXPelsPerMeter=_bih.biClrUsed=_bih.biYPelsPerMeter=0; _mainaviheader.dwTotalFrames= _incoming->getInfo ()->nb_frames; _mainaviheader.dwMicroSecPerFrame=0; printf("\n Saved as %ld x %ld\n",_bih.biWidth,_bih.biHeight); _bih.biCompression=fourCC::get((uint8_t *)_encode->getCodecName()); encoding_gui->setCodec(_encode->getDisplayName()); // init save avi //-----------------------2 Pass-------------------------------------- if (_encode->isDualPass ()) { uint8_t *buffer; uint32_t len, flag; int r, frameDelay = 0; aprintf("\n** Dual pass encoding**\n"); if(!reuse) { guiSetPhasis (QT_TR_NOOP("1st Pass")); aprintf("**Pass 1:%lu\n",frametogo); buffer = new uint8_t[_incoming->getInfo ()->width * _incoming->getInfo ()->height * 3]; _encode->startPass1 (); bitstream.bufferSize = _incoming->getInfo()->width * _incoming->getInfo()->height * 3; bitstream.data=buffer; for (uint32_t cf = 0; cf < frametogo; cf++) { if (guiUpdate (cf, frametogo)) { abt: GUI_Error_HIG (QT_TR_NOOP("Aborting"), NULL); delete[] buffer; return 0; } for (;;) { bitstream.cleanup(cf); if (cf + frameDelay >= frametogo) { if (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH) r = _encode->encode(UINT32_MAX, &bitstream); else r = 0; } else r = _encode->encode(cf + frameDelay, &bitstream); if (!r) { printf("Encoding of frame %lu failed!\n", cf); goto abt; } if (bitstream.len == 0 && (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH)) { printf("skipping frame: %u size: %i\n", cf + frameDelay, bitstream.len); frameDelay++; } else break; } encoding_gui->setFrame(cf,bitstream.len,bitstream.out_quantizer,frametogo); } encoding_gui->reset(); delete[]buffer; aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } } //-------------------------/VBR----------------------------------- // init save avi // now we build the new stream ! aprintf("**main pass:\n"); memcpy(&_videostreamheader,video_body->getVideoStreamHeader (),sizeof(_videostreamheader)); memcpy(&_videostreamheader.fccHandler ,_encode->getFCCHandler(),4); _videostreamheader.fccType =fourCC::get((uint8_t *)"vids"); _videostreamheader.dwScale=1000; _videostreamheader.dwRate= _incoming->getInfo ()->fps1000; memcpy(&_mainaviheader ,video_body->getMainHeader (),sizeof(_mainaviheader)); _mainaviheader.dwWidth=_bih.biWidth; _mainaviheader.dwHeight=_bih.biHeight; _videostreamheader.dwQuality=10000; uint8_t *data; uint32_t dataLen=0; _encode->hasExtraHeaderData( &dataLen,&data); if (!writter->saveBegin (name, &_mainaviheader, frameEnd - frameStart + 1, &_videostreamheader, &_bih, data,dataLen, (AVDMGenericAudioStream *) audio_filter, NULL)) { return 0; } aprintf("Setup video done\n"); bitstream.data=vbuffer; bitstream.bufferSize=MAXIMUM_SIZE * MAXIMUM_SIZE * 3; return 1; //--------------------- }
void A_SaveAudioNVideo(char *name) { uint32_t needSmart=0,fl; GenericAviSave *nw; aviInfo info; video_body->getVideoInfo(&info); printf("\n video process mode : %d",videoProcessMode); if (!videoProcessMode) { if(video_body->isMultiSeg()) needSmart=1; video_body->getFlags(frameStart,&fl); if(!(fl&AVI_KEY_FRAME)) needSmart=1; if(needSmart) printf("\n probably need smart copy mode\n"); if( !isMpeg4Compatible( info.fcc) #ifdef USE_FFMPEG && !isMSMpeg4Compatible(info.fcc) #endif ) { printf("\n not encodable, cancelling smart mode\n"); needSmart=0; } #ifdef HAVE_ENCODER if(needSmart && GUI_Question("You may need smart copy.\n Enable it ?")) { nw=new GenericAviSaveSmart; } else { nw=new GenericAviSaveCopy; } #else nw=new GenericAviSaveCopy; #endif } else { #ifdef HAVE_ENCODER printf("\n Process mode\n"); nw=new GenericAviSaveProcess; #else GUI_Alert("\n No encoder , cannot save in process mode"); return ; #endif } if(!nw->saveAvi(name)) { GUI_Alert(" AVI NOT saved"); } else GUI_Alert(" Saved successfully"); delete nw; }
/** \fn dmx_indexer \brief Create index file @param mpeg Name of the file to index @param file Name of the index file to create @param preferedAudio Default audio track @param nbTracks # of tracks, including video @param tracks track descriptor @return 1 on success, 0 on failure The incoming file can be mpeg PS/TS/ES or ASF. The payload can be mostly mpeg2, with some work done to support later mpeg4/H264 in TS mostly */ uint8_t dmx_indexer(const char *mpeg,const char *file,uint32_t preferedAudio,uint8_t autosync,uint32_t nbTracks,MPEG_TRACK *tracks) { DIA_progressIndexing *work; dmx_demuxer *demuxer; char *realname=PathCanonize(mpeg); FILE *out; DMX_TYPE mpegType; uint8_t mpegTypeChar; uint32_t multi=0; dmx_payloadType payloadType=DMX_PAYLOAD_MPEG2; mpegType=dmxIdentify(realname); if(mpegType==DMX_MPG_UNKNOWN) { delete [] realname; return 0; } switch(mpegType) { case DMX_MPG_MSDVR: { dmx_demuxerMSDVR *dmx; dmx=new dmx_demuxerMSDVR(nbTracks,tracks,0); demuxer=dmx; mpegTypeChar='M'; break; } case DMX_MPG_TS: case DMX_MPG_TS2: { dmx_demuxerTS *dmx; dmx=new dmx_demuxerTS(nbTracks,tracks,0,mpegType); demuxer=dmx; switch(mpegType) { case DMX_MPG_TS :mpegTypeChar='T';break; case DMX_MPG_TS2 :mpegTypeChar='S';break; default: ADM_assert(0); } switch(tracks[0].streamType) { case ADM_STREAM_H264: payloadType=DMX_PAYLOAD_H264;break; case ADM_STREAM_MPEG4: payloadType=DMX_PAYLOAD_MPEG4;break; case ADM_STREAM_MPEG_VIDEO: payloadType=DMX_PAYLOAD_MPEG2;break; default: ADM_assert(0); } break; } case DMX_MPG_ES: demuxer=new dmx_demuxerES; mpegTypeChar='E'; break; case DMX_MPG_H264_ES: payloadType=DMX_PAYLOAD_H264; demuxer=new dmx_demuxerES; mpegTypeChar='E'; break; case DMX_MPG_PS: { dmx_demuxerPS *dmx; fileParser *fp; FP_TYPE type=FP_PROBE; fp=new fileParser; fp->open(realname,&type); delete fp; if(type==FP_APPEND) { if(GUI_Question(QT_TR_NOOP("There is several mpeg file, append them ?"))) multi=1; } dmx=new dmx_demuxerPS(nbTracks,tracks,multi); demuxer=dmx; mpegTypeChar='P'; } break; default : ADM_assert(0); } demuxer->open(realname); out=qfopen(file,"wt"); if(!out) { printf("\n Error : cannot open index !"); delete demuxer; delete [] realname; return 0; } qfprintf(out,"ADMY0003\n"); qfprintf(out,"Type : %c\n",mpegTypeChar); // ES for now qfprintf(out,"File : %s\n",realname); qfprintf(out,"Append : %d\n",multi); qfprintf(out,"Image : %c\n",'P'); // Progressive qfprintf(out,"Picture : %04lu x %04lu %05lu fps\n",0,0,0); // width... qfprintf(out,"Payload : %c%c%c%c\n",'M','P','E','G'); // width... qfprintf(out,"Nb Gop : %08lu \n",0); // width... qfprintf(out,"Nb Images: %010lu \n",0); // width... qfprintf(out,"Nb Audio : %02lu\n",nbTracks-1); qfprintf(out,"Main aud : %02lu\n",preferedAudio); qfprintf(out,"Streams : "); for(int s=0;s<nbTracks;s++) { if(!s){ qfprintf(out,"V%04x:%04x ",tracks[0].pid,tracks[0].pes); }else{ qfprintf(out,"A%04x:%04x ",tracks[s].pid,tracks[s].pes); } } qfprintf(out,"\n"); qfprintf(out,"# NGop NImg nbImg type:abs:rel:size ...\n"); uint8_t grabbing=0,seq_found=0; uint32_t total_frame=0,val; uint32_t originalPriority = getpriority(PRIO_PROCESS, 0); uint32_t priorityLevel; prefs->get(PRIORITY_INDEXING,&priorityLevel); setpriority(PRIO_PROCESS, 0, ADM_getNiceValue(priorityLevel)); work=new DIA_progressIndexing(mpeg); printf("*********Indexing started (%d audio tracks)***********\n",nbTracks); dmx_runData run; memset(&run,0,sizeof(dmx_runData)); run.totalFileSize=demuxer->getSize(); run.demuxer=demuxer; run.work=work; run.nbTrack=nbTracks; run.fd=out; dmx_videoIndexer *idxer=NULL; switch(payloadType) { case DMX_PAYLOAD_MPEG2: { idxer=new dmx_videoIndexerMpeg2(&run); break; } case DMX_PAYLOAD_MPEG4:ADM_assert(0); case DMX_PAYLOAD_H264: idxer=new dmx_videoIndexerH264(&run); break; default: ADM_assert(0); } idxer->run(); idxer->cleanup(); delete idxer; idxer=NULL; printf("*********Indexing Ended (%d audio tracks)***********\n",nbTracks); switch(run.imageAR) { case 1: qfprintf(out,"# Video Aspect Ratio : %s\n", "1:1" );break; case 2: qfprintf(out,"# Video Aspect Ratio : %s\n", "4:3" );break; case 3: qfprintf(out,"# Video Aspect Ratio : %s\n", "16:9" );break; default: printf("imageAR=%u\n",run.imageAR); GUI_Error_HIG(QT_TR_NOOP("Can't determine aspect ratio"),NULL); } /* Now update......... */ fseeko(out,0,SEEK_SET); // Update if needed uint32_t compfps,delta=computeTimeDifference(&(run.firstStamp),&(run.lastStamp)); delta=delta/1000; // in second if(delta) { compfps= (1000*run.nbImage)/delta; // 3 Million images should be enough, no overflow } else { compfps=run.imageFPS; } // Detect film (i.e. NTSC with computed fps close to 24) if(run.imageFPS==29970 || run.imageFPS==30000) { if(compfps>23800 && compfps < 24200) run.imageFPS=23976; } // Detect interlaced vs progressive // If field encoded, the average fps is about twice as theoritical fps char type='P'; float err; err=run.imageFPS*2; err-=compfps; err*=100; err/=run.imageFPS*2; if(err<0) err=-err; printf("%lu :%lu / %lu , %f\n",run.imageFPS,run.imageFPS*2,compfps,err); if(err<10) { type='I'; printf("Seems to be field encoded\n"); } else { printf("Seems to be frame encoded\n"); } // Now dump the delta PTS // *****************Update header************* qfprintf(out,"ADMY0003\n"); qfprintf(out,"Type : %c\n",mpegTypeChar); // ES for now qfprintf(out,"File : %s\n",realname); qfprintf(out,"Append : %d\n",multi); qfprintf(out,"Image : %c\n",type); // Progressive qfprintf(out,"Picture : %04lu x %04lu %05lu fps\n",run.imageW,run.imageH,run.imageFPS); // width... switch(payloadType) { case DMX_PAYLOAD_MPEG2: qfprintf(out,"Payload : MPEG\n"); // MPEG,MP_4,H264 break; case DMX_PAYLOAD_MPEG4: qfprintf(out,"Payload : MP_4\n"); // MPEG,MP_4,H264 break; case DMX_PAYLOAD_H264: qfprintf(out,"Payload : H264\n"); // MPEG,MP_4,H264 break; default: ADM_assert(0); } qfprintf(out,"Nb Gop : %08lu \n",run.nbGop); // width... qfprintf(out,"Nb Images: %010lu \n",run.nbImage); // width... qfclose(out); delete work; printf("*********Indexing stopped***********\n"); printf("Found :%lu gop\n",run.nbGop); printf("Found :%lu image\n",run.nbImage); printf("Average fps :%lu /1000 fps\n",compfps); delete demuxer; delete [] realname; setpriority(PRIO_PROCESS, 0, originalPriority); return 1; }
uint8_t prepareDualPass(uint32_t bufferSize,uint8_t *buffer,char *TwoPassLogFile,DIA_encoding *encoding_gui,Encoder *_encode,uint32_t total) { uint32_t len, flag; FILE *tmp; uint8_t reuse=0,r; ADMBitstream bitstream(0); uint32_t prefill=0; uint32_t sent=0; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question(QT_TR_NOOP("\n Reuse the existing log-file ?"))) { reuse=1; } } if(!reuse) { encoding_gui->setPhasis ("1st Pass"); aprintf("**Pass 1:%lu\n",total); _encode->startPass1 (); bitstream.data=buffer; bitstream.bufferSize=bufferSize; preFilling2: bitstream.cleanup(0); if(!_encode->encode ( prefill, &bitstream))//&len, videoBuffer, &flags,&displayFrame)) { printf("MP4:First frame error\n"); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); return 0; } sent++; if(!bitstream.len) { prefill++; goto preFilling2; } printf("Pass 1 prefill : %u\n",prefill); for (uint32_t cf = 1; cf < total; cf++) { if (!encoding_gui->isAlive()) { abt: GUI_Error_HIG (QT_TR_NOOP("Aborting"), NULL); return 0; } bitstream.cleanup(cf); if(!prefill || cf+prefill<total) { r=_encode->encode ( prefill+cf, &bitstream); } else { r=_encode->encode ( total-1, &bitstream); } if (!r) { printf("\n Encoding of frame %lu failed !\n",cf); return 0; } sent++; encoding_gui->setFrame(cf,bitstream.len,bitstream.out_quantizer,total); } encoding_gui->reset(); aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } printf("First pass : send %u frames\n",sent); encoding_gui->setPhasis ("2nd Pass"); return 1; }
void HandleAction (Action action) { uint32_t nf = 0; uint32_t old; admScopedMutex autolock(&singleThread); // make sure only one thread at a time calls this ADM_warning("************ %s **************\n",getActionName(action)); // handle out of band actions // independant load not loaded //------------------------------------------------ if(action==ACT_RUN_SCRIPT) { GUI_FileSelRead("Select script/project to run", A_RunScript); return; } if (action >= ACT_SCRIPT_ENGINE_FIRST && action < ACT_SCRIPT_ENGINE_LAST) { int engineIndex = (action - ACT_SCRIPT_ENGINE_FIRST) / 3; int actionId = (action - ACT_SCRIPT_ENGINE_FIRST) % 3; tempEngine = getScriptEngines()[engineIndex]; switch (actionId) { case 0: GUI_FileSelRead("Select script to run", RunScript); break; case 1: GUI_FileSelRead("Select script to debug", DebugScript); break; case 2: GUI_FileSelWrite(QT_TRANSLATE_NOOP("adm","Select script to save"), SaveScript); UI_refreshCustomMenu(); break; } return; } if (action >= ACT_SCRIPT_ENGINE_SHELL_FIRST && action < ACT_SCRIPT_ENGINE_SHELL_LAST) { IScriptEngine *shellEngine = getScriptEngines()[action - ACT_SCRIPT_ENGINE_SHELL_FIRST]; if ((shellEngine->capabilities() & IScriptEngine::DebuggerShell) == IScriptEngine::DebuggerShell) { shellEngine->openDebuggerShell(); } else { interactiveScript(shellEngine); } return; } switch (action) { case ACT_TimeShift: A_TimeShift(); return; case ACT_Goto: brokenAct(); return; case ACT_AVS_PROXY: GUI_avsProxy(); return; case ACT_BUILT_IN: DIA_builtin(); return; case ACT_RECENT0: case ACT_RECENT1: case ACT_RECENT2: case ACT_RECENT3: { const char **name; int rank; name=prefs->get_lastfiles(); rank=(int)action-ACT_RECENT0; ADM_assert(name[rank]); A_openAvi (name[rank]); return; } case ACT_RECENT_PROJECT0: case ACT_RECENT_PROJECT1: case ACT_RECENT_PROJECT2: case ACT_RECENT_PROJECT3: { const char **name = prefs->get_lastprojectfiles(); int rank = (int)action - ACT_RECENT_PROJECT0; ADM_assert(name[rank]); call_scriptEngine(name[rank]); return; } case ACT_VIDEO_CODEC_CONFIGURE: videoEncoder6Configure(); return; case ACT_ContainerConfigure: { int index=UI_GetCurrentFormat(); ADM_mux_configure(index); return; } case ACT_VIDEO_CODEC_CHANGED: { int nw=UI_getCurrentVCodec(); videoEncoder6_SetCurrentEncoder(nw); return; } case ACT_AUDIO_CODEC_CHANGED: { int nw=UI_getCurrentACodec(); audioCodecSetByIndex(0,nw); return; } case ACT_PLUGIN_INFO: DIA_pluginsInfo(); return; case ACT_OPEN_APP_LOG: GUI_OpenApplicationLog(); return; case ACT_OPEN_APP_FOLDER: GUI_OpenApplicationDataFolder(); return; case ACT_ABOUT : DIA_about( ); return; case ACT_AUDIO_CODEC_CONFIGURE: audioCodecConfigure(0); return; case ACT_AUDIO_FILTERS: { EditableAudioTrack *ed=video_body->getDefaultEditableAudioTrack(); if(ed) ed->audioEncodingConfig.audioFilterConfigure(); } return; case ACT_PREFERENCES: if(playing) return; if(DIA_Preferences()) { ADM_info("Saving prefs\n"); prefs->save (); } return; case ACT_SavePref: prefs->save (); return; case ACT_EXIT: if(playing) { ADM_info("Stopping playback...\n"); GUI_PlayAvi(); } ADM_info("Closing ui\n"); UI_closeGui(); return; break; default: break; } if (playing) // only allow some action { switch (action) { case ACT_PlayAvi: case ACT_StopAvi: break; default: return; } } // not playing, // restict disabled uncoded actions if ((int) action >= ACT_DUMMY) { GUI_Error_HIG (QT_TRANSLATE_NOOP("adm","Not coded in this version"), NULL); return; } // allow only if avi loaded if (!avifileinfo) { switch (action) { case ACT_JOG: break; case ACT_OPEN_VIDEO: GUI_FileSelRead (QT_TRANSLATE_NOOP("adm","Select Video File..."), (SELFILE_CB *)A_openAvi); break; default: break; } return; } // Dispatch actions, we have a file loaded if(action>ACT_NAVIGATE_BEGIN && action < ACT_NAVIGATE_END) { return HandleAction_Navigate(action); } if(action>ACT_SAVE_BEGIN && action < ACT_SAVE_END) { return HandleAction_Save(action); } switch (action) { case ACT_SAVE_PY_SCRIPT: { IScriptEngine *engine=getPythonScriptEngine(); if(!engine) { GUI_Error_HIG("No engine","tinyPy script is not enabled in this build"); break; } char fileName[1024]; if(FileSel_SelectWrite("Saving tinypy project",fileName,1000, NULL)) { int l=strlen(fileName); if(l>3) { char *tail=fileName+l-3; if(tail[0]!='.'|| tail[1]!='p'|| tail[2]!='y') strcat(fileName,".py"); } A_saveScript(engine, fileName); } break; } break; case ACT_JOG: A_jog(); break; case ACT_CLOSE: GUI_close(); break; case ACT_ZOOM_1_4: case ACT_ZOOM_1_2: case ACT_ZOOM_1_1: case ACT_ZOOM_2_1: case ACT_ZOOM_4_1: currentZoom=(renderZoom)((action-ACT_ZOOM_1_4)+ZOOM_1_4); changePreviewZoom(currentZoom); admPreview::samePicture(); break; case ACT_AUDIO_SELECT_TRACK: A_audioTrack(); break; case ACT_OPEN_VIDEO: GUI_FileSelRead (QT_TRANSLATE_NOOP("adm","Select Video File..."),(SELFILE_CB *) A_openAvi); break; case ACT_APPEND_VIDEO: GUI_FileSelRead (QT_TRANSLATE_NOOP("adm","Select Video File to Append..."),(SELFILE_CB *) A_appendAvi); break; case ACT_VIDEO_PROPERTIES: DIA_properties (); break; case ACT_PlayAvi: GUI_PlayAvi (); break; #define TOGGLE_PREVIEW ADM_PREVIEW_OUTPUT case ACT_PreviewChanged: { ADM_PREVIEW_MODE oldpreview=getPreviewMode(),newpreview=(ADM_PREVIEW_MODE)UI_getCurrentPreview(); printf("Old preview %d, New preview mode : %d\n",oldpreview,newpreview); if(oldpreview==newpreview) { return; } admPreview::stop(); setPreviewMode(newpreview); admPreview::start(); // admPreview::update(curframe); } break; case ACT_StopAvi: if (playing) GUI_PlayAvi (); break; case ACT_SetPostProcessing: A_setPostproc(); break; case ACT_MarkA: case ACT_MarkB: { bool swapit=0; uint64_t markA,markB; uint64_t pts=admPreview::getCurrentPts(); if( prefs->get(FEATURES_SWAP_IF_A_GREATER_THAN_B, &swapit) != RC_OK ) swapit = 1; markA=video_body->getMarkerAPts(); markB=video_body->getMarkerBPts(); if (action == ACT_MarkA) markA=pts; else markB=pts; if (markA>markB && swapit ) // auto swap { uint64_t y; y = markA; markA=markB; markB=y; } video_body->setMarkerAPts(markA); video_body->setMarkerBPts(markB); UI_setMarkers (markA, markB); break; } case ACT_Copy: { uint64_t markA,markB; markA=video_body->getMarkerAPts(); markB=video_body->getMarkerBPts(); if(markA>markB) { uint64_t p=markA; markA=markB; markB=p; } video_body->copyToClipBoard (markA,markB); break; } case ACT_Paste: { uint64_t currentPts=video_body->getCurrentFramePts(); video_body->pasteFromClipBoard(currentPts); video_body->getVideoInfo (avifileinfo); A_ResetMarkers(); ReSync (); } break; break; case ACT_Undo: if (avifileinfo) { uint64_t currentPts=video_body->getCurrentFramePts(); if(video_body->undo()) { video_body->getVideoInfo(avifileinfo); ReSync(); A_ResetMarkers(); A_Rewind(); if(currentPts<=video_body->getVideoDuration()) GUI_GoToTime(currentPts); } } break; case ACT_ResetSegments: if(avifileinfo) if(GUI_Question(QT_TRANSLATE_NOOP("adm","Are you sure?"))) { video_body->resetSeg(); video_body->getVideoInfo (avifileinfo); A_ResetMarkers(); ReSync (); // forget last project file video_body->setProjectName(""); } break; case ACT_Delete: case ACT_Cut: { uint64_t a=video_body->getMarkerAPts(); uint64_t b=video_body->getMarkerBPts(); if(false==video_body->remove(a,b)) { GUI_Error_HIG("Cutting","Error while cutting out."); } else { A_ResetMarkers(); A_Resync(); // total duration & stuff // Rewind to first frame... //A_Rewind(); GUI_GoToTime(a); } } break; // set decoder option (post processing ...) case ACT_DecoderOption: video_body->setDecodeParam ( admPreview::getCurrentPts()); break; case ACT_VIDEO_FILTERS: GUI_handleVFilter(); break; case ACT_HEX_DUMP: GUI_showCurrentFrameHex(); break; case ACT_SIZE_DUMP: GUI_showSize(); break; case ACT_TimeShift: A_TimeShift(); break; default: printf ("\n unhandled action %d\n", action); ADM_assert (0); return; } }
uint8_t GenericAviSaveProcess::setupVideo (char *name) { _notnull=0; _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); frametogo=_incoming->getInfo()->nb_frames; encoding_gui->setFps(_incoming->getInfo()->fps1000); // anish if(_incoming->getInfo()->width%8) { if(!GUI_Question("Width is not a multiple of 8\n continue anyway ?")) return 0; } _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height); if (!_encode) return 0; // init compressor TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,frametogo); if (!_encode->configure (_incoming)) { delete _encode; _encode = NULL; GUI_Error_HIG ("Filter init failed", NULL); return 0; }; memcpy (&_bih, video_body->getBIH (), sizeof (_bih)); _bih.biWidth = _incoming->getInfo ()->width; _bih.biHeight = _incoming->getInfo ()->height; _bih.biSize=sizeof(_bih); _bih.biXPelsPerMeter=_bih.biClrUsed=_bih.biYPelsPerMeter=0; _mainaviheader.dwTotalFrames= _incoming->getInfo ()->nb_frames; _mainaviheader.dwMicroSecPerFrame=0; printf("\n Saved as %ld x %ld\n",_bih.biWidth,_bih.biHeight); _bih.biCompression=fourCC::get((uint8_t *)_encode->getCodecName()); encoding_gui->setCodec(_encode->getDisplayName()); // init save avi //-----------------------VBR-------------------------------------- if (_encode->isDualPass ()) { uint8_t *buffer; uint32_t len, flag; FILE *tmp; uint8_t reuse=0; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question("\n Reuse the existing log-file ?")) { reuse=1; } } if(!reuse) { guiSetPhasis ("1st Pass"); aprintf("**Pass 1:%lu\n",frametogo); buffer = new uint8_t[_incoming->getInfo ()->width * _incoming->getInfo ()->height * 3]; _encode->startPass1 (); //__________________________________ // now go to main loop..... //__________________________________ for (uint32_t cf = 0; cf < frametogo; cf++) { if (guiUpdate (cf, frametogo)) { abt: GUI_Error_HIG ("Aborting", NULL); delete[]buffer; return 0; } if (!_encode->encode (cf, &len, buffer, &flag)) { printf("\n Encoding of frame %lu failed !\n",cf); goto abt; } encoding_gui->setQuant(_encode->getLastQz()); encoding_gui->feedFrame(len); } // guiStop (); encoding_gui->reset(); delete[]buffer; aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } } //-------------------------/VBR----------------------------------- // init save avi // now we build the new stream ! aprintf("**main pass:\n"); memcpy(&_videostreamheader,video_body->getVideoStreamHeader (),sizeof(_videostreamheader)); memcpy(&_videostreamheader.fccHandler ,_encode->getFCCHandler(),4); _videostreamheader.fccType =fourCC::get((uint8_t *)"vids"); _videostreamheader.dwScale=1000; _videostreamheader.dwRate= _incoming->getInfo ()->fps1000; memcpy(&_mainaviheader ,video_body->getMainHeader (),sizeof(_mainaviheader)); _mainaviheader.dwWidth=_bih.biWidth; _mainaviheader.dwHeight=_bih.biHeight; _videostreamheader.dwQuality=10000; uint8_t *data; uint32_t dataLen=0; _encode->hasExtraHeaderData( &dataLen,&data); if (!writter->saveBegin (name, &_mainaviheader, frameEnd - frameStart + 1, &_videostreamheader, &_bih, data,dataLen, (AVDMGenericAudioStream *) audio_filter, NULL)) { return 0; } aprintf("Setup video done\n"); return 1; //--------------------- }
//________________________________________________ uint8_t ADM_ogmWriteProcess::initVideo(char *name) { uint32_t w,h,fps1000,fcc; _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); _togo=_incoming->getInfo()->nb_frames; _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height); if (!_encode) return 0; TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,_togo); if (!_encode->configure (_incoming)) { delete _encode; _encode = NULL; GUI_Alert ("Init of filter failed"); return 0; }; w= _incoming->getInfo ()->width; h=_incoming->getInfo ()->height; fps1000=_incoming->getInfo ()->fps1000; _fps1000=fps1000; fcc= fourCC::get((uint8_t *)_encode->getCodecName()); _videoBuffer=new uint8_t[w*h*3]; encoding_gui->setCodec(_encode->getDisplayName()); //-----------------------VBR-------------------------------------- if (_encode->isDualPass ()) { uint8_t *buffer; uint32_t len, flag; FILE *tmp; uint8_t reuse=0; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question("\n Reuse the existing log-file ?")) { reuse=1; } } if(!reuse) { aprintf("**Pass 1:%lu\n",_togo); _encode->startPass1 (); encoding_gui->setCodec((char *)_encode->getCodecName()); encoding_gui->setPhasis("Pass one"); //__________________________________ // now go to main loop..... //__________________________________ for (uint32_t cf = 0; cf < _togo; cf++) { if (!_encode->encode (cf, &len, _videoBuffer, &flag)) { printf("\n Encoding of frame %lu failed !\n",cf); return 0; } encoding_gui->feedFrame(len); encoding_gui->setFrame(cf,_togo); encoding_gui->setQuant(_encode->getLastQz()); if(!encoding_gui->isAlive()) { return 0; } } aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } encoding_gui->setPhasis("Pass 2"); } //-------------------------/VBR----------------------------------- else { encoding_gui->setPhasis("Encoding"); } // init save avi // now we build the new stream ! aprintf("**main pass:\n"); stream_header header; int64_t dur64; uint32_t dur32; uint16_t dur16; memset(&header,0,sizeof(header)); memcpy(&(header.streamtype),"video\0\0\0",8); MEMCPY(&(header.subtype),&fcc,4); //header.size=sizeof(header); dur32=sizeof(header); MEMCPY(&header.size,&dur32,4); MEMCPY(&(header.video.width),&w,4); MEMCPY(&(header.video.height),&h,4); // Timing .. double duration; // duration in 10us duration=fps1000; duration=1000./duration; duration*=1000*1000; duration*=10; dur64=(int64_t)duration; MEMCPY(&header.time_unit,&dur64,8); dur64=1; MEMCPY(&header.samples_per_unit,&dur64,8); dur32=0x10000; MEMCPY(&header.buffersize,&dur32,4); dur16=24; MEMCPY(&header.bits_per_sample,&dur16,2); //header.default_len=1; dur32=1; MEMCPY(&header.default_len,&dur32,4); return videoStream->writeHeaders(sizeof(header),(uint8_t *)&header); // +4 ? }
int A_Save(const char *name) { uint32_t end; int ret=0; // depending on the type we save a avi, a mpeg or a XVCD CodecFamilty family; family= videoCodecGetFamily(); // in case of copy mode, we stick to avi file format if(!videoProcessMode()) { family=CodecFamilyAVI; if( UI_GetCurrentFormat()==ADM_PS ||UI_GetCurrentFormat()==ADM_TS ) // exception { family=CodecFamilyMpeg; } } else { if(UI_GetCurrentFormat()==ADM_AVI_DUAL) { GUI_Error_HIG(QT_TR_NOOP("Dual audio can only be used in copy mode"),QT_TR_NOOP( "Select Copy as the video codec.")); return 0; } } printf("**saving:**\n"); // Check if we need to do a sanity B frame check if(!videoProcessMode()) { uint32_t pb; end=avifileinfo->nb_frames; // if the last frame is the last frame (!) // we add one to keep it, else we systematically skip // the last frame #if 0 if(frameEnd==end-1) end=frameEnd+1; else end=frameEnd; if(!video_body->sanityCheckRef(frameStart,end,&pb)) { if(pb) { GUI_Error_HIG("Cannot save the file", "The video starts/ends with a lonely B-frame. Please remove it."); return 0; } if(!GUI_Question("Warning !\n Bframe has lost its reference frame\nContinue ?")) return 0; } #endif // Alter frameEnd so that it is not a B frame // as frameEnd -1 position uint32_t tgt=frameEnd;; uint32_t flag=0,found=0; // need to do something ? if(frameEnd>frameStart) { tgt=frameEnd; if(tgt==end-1) tgt++; video_body->getFlags(tgt-1,&flag); if((frameEnd&AVI_B_FRAME)) { printf("Last frame is a B frame, choosing better candidate\n"); // The last real one is not a I/P Frame // Go forward or rewind if(tgt<end-1) { // Try next if possible video_body->getFlags(tgt,&flag); if(!(flag&AVI_B_FRAME)) { printf("Taking next frame as last frame %lu\n",tgt+1); frameEnd=tgt+1; found=1; } } if(!found) // next frame not possible, rewind { if(tgt>=end-2) tgt=end-2; while(tgt>frameStart) { printf("Trying :%lu\n",tgt); video_body->getFlags(tgt,&flag); if(!(flag&AVI_B_FRAME)) { printf("Taking previous frame as last frame %lu\n",tgt+1); frameEnd=tgt+1; found=1; break; } else tgt--; } } ADM_assert(found); } } } printf("Output format:%d\n",UI_GetCurrentFormat()); switch(family) { case CodecFamilyAVI: printf(" AVI family\n"); switch(UI_GetCurrentFormat()) { case ADM_DUMMY: ret=oplug_dummy(name); break; case ADM_FLV: ret=oplug_flv(name); break; case ADM_MP4: case ADM_PSP: case ADM_MATROSKA: ret=oplug_mp4(name,UI_GetCurrentFormat()); break; case ADM_AVI: ret=A_SaveAudioNVideo(name); break; case ADM_OGM: ret=ogmSave(name); break; case ADM_ES: ret=ADM_saveRaw(name); break; case ADM_AVI_DUAL: ret=A_SaveAudioDualAudio(name); break; case ADM_AVI_PAK: ret=A_SavePackedVop(name); break; case ADM_AVI_UNP: ret=A_SaveUnpackedVop(name); break; default: GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL); } break; case CodecFamilyMpeg: printf(" MPEG family\n"); if(!videoProcessMode()) { printf("Using pass through\n"); switch(UI_GetCurrentFormat()) { case ADM_PS: case ADM_TS: ret=mpeg_passthrough(name,UI_GetCurrentFormat()); break; default: GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL); } break; } // THERE IS NO BREAK HERE, NOT A MISTAKE! case CodecFamilyXVCD: switch(UI_GetCurrentFormat()) { case ADM_TS: case ADM_PS: case ADM_ES: ret=oplug_mpegff(name,UI_GetCurrentFormat());; break; default: GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL); } break; default: ADM_assert(0); return 0; } getFirstVideoFilter(0,avifileinfo->nb_frames); return ret; }