/** \fn parseMvhd \brief Parse mvhd header */ void MP4Header::parseMvhd(void *ztom) { adm_atom *tom = (adm_atom*)ztom; int version = tom->read(); tom->skipBytes(3); // flags if (version == 1) tom->skipBytes(16); else tom->skipBytes(8); int scale = tom->read32(); uint64_t duration = (version == 1) ? tom->read64() : tom->read32(); _videoScale = scale; printf("Warning: scale is not in ms %lu!\n", _videoScale); if (_videoScale) { duration = 1000 * duration; // In ms duration /= _videoScale; } else _videoScale = 1000; printf("Movie duration: %s\n", ms2timedisplay(duration)); _movieDuration = duration; }
uint8_t DIA_workingQt4::update(uint32_t percent) { #define GUI_UPDATE_RATE 1000 UI_purge(); if(!_priv) return 1; if(!percent) return 0; if(percent==lastper) { return 0; } elapsed=_clock.getElapsedMS(); if(elapsed<_nextUpdate) { return 0; } _nextUpdate=elapsed+1000; lastper=percent; uint32_t hh,mm,ss,mms; char string[9]; ms2time(elapsed,&hh,&mm,&ss,&mms); sprintf(string,"%02d:%02d:%02d",hh,mm,ss); workWindow *wind=(workWindow *)_priv; ADM_assert(wind); if(percent>=1) { double totalTime=(100*elapsed)/percent; double remaining=totalTime-elapsed; if(remaining<0) remaining=0; uint32_t remainingMs=(uint32_t)remaining; wind->ui->labelTimeLeft->setText(ms2timedisplay(remainingMs)); } wind->ui->labelElapsed->setText(string); wind->ui->progressBar->setValue(percent); return 0; }
/** \fn parseMvhd \brief Parse mvhd header */ void MP4Header::parseMvhd(void *ztom) { adm_atom *tom=(adm_atom *)ztom; tom->skipBytes(12); uint32_t scale,duration=1000; scale=tom->read32(); duration=tom->read32(); _videoScale=scale; printf("Warning : scale is not in ms %lu !\n",_videoScale); if(_videoScale) { duration=1000*duration; // In ms duration/=_videoScale; }else _videoScale=1000; printf("Movie duration :%s\n",ms2timedisplay(duration)); _movieDuration=duration; }
uint8_t DIA_working::update(uint32_t percent) { #define GUI_UPDATE_RATE 1000 UI_purge(); if(!_priv) return 1; if(!percent) return 0; if(percent==lastper) { return 0; } elapsed=_clock.getElapsedMS(); if(elapsed<_nextUpdate) { return 0; } _nextUpdate=elapsed+1000; lastper=percent; uint32_t hh,mm,ss; char string[9]; ms2time(elapsed,&hh,&mm,&ss); sprintf(string,"%02d:%02d:%02d",hh,mm,ss); workWindow *wind=(workWindow *)_priv; ADM_assert(wind); wind->ui.labelTimeLeft->setText(ms2timedisplay((uint32_t) floor(((elapsed * 100.) / percent) - elapsed))); wind->ui.labelElapsed->setText(string); wind->ui.progressBar->setValue(percent); return 0; }
uint8_t ADM_Composer::getAudioPacket(uint8_t *dest, uint32_t *len, uint32_t *samples) { uint8_t r; uint32_t ref; _VIDEOS *currentVideo; currentVideo=&_videos[AUDIOSEG]; if(_audioSample<_segments[_audioseg]._audio_duration) { if( !currentVideo->_audiostream) { printf("No soundtrack"); *len=0; *samples=0; return 0; } r=currentVideo->_audiostream->getPacket(dest,len,samples); if(r) { // ok we update the current sample count and go on _audioSample+=*samples; return r; } // could not get the cound, rewind and retry printf("EditorPacket:Read failed; retrying (were at seg %u" ,_audioseg); printf("sample %u\n",_audioSample); // FIXME use proper stuff printf("/ %d)\n",_segments[_audioseg]._audio_duration); if(_audioseg == (_nb_segment - 1)) { printf("EditorPacket : End of *last* stream\n"); return 0; } // If we get here, it means we have less audio that it should // In the current segment. Generally we repeat the segment // Except if the missing data is less than 20 ms, we will compensate later float drift; drift=(float)_segments[_audioseg]._audio_duration; drift-=(float)_audioSample; drift/=(float)currentVideo->_audiostream->getInfo()->frequency; drift*=1000.; printf("Seg :%u, Drop %3.3f ms\n",_audioseg,drift); if(drift>10.) { printf("Drop too high, filling...\n"); currentVideo->_audiostream->goToTime(0); r=currentVideo->_audiostream->getPacket(dest,len,samples); if(r) { printf("Filled with data from beginning (%u bytes %u samples)\n",*len,*samples); // read it again sam _audioSample+=*samples; } return r; } } // We have to switch seg // We may have overshot a bit, but... // this is the end ? if(_audioseg == (_nb_segment - 1)) { printf("EditorPacket : End of stream Segment :%u/%u \n",_audioseg,_nb_segment); printf("This sample : %u (%s) ",_audioSample,ms2timedisplay(1000*_audioSample/currentVideo->_audiostream->getInfo()->frequency)); printf("total :%u (%s)\n" ,_segments[_audioseg]._audio_duration,ms2timedisplay(1000*_segments[_audioseg]._audio_duration/currentVideo->_audiostream->getInfo()->frequency)); return 0; } // switch segment // We adjust the audiosample to avoid adding cumulative shift uint8_t ret; int64_t adjust=_audioSample-=_segments[_audioseg]._audio_duration; if(adjust>0) _audioSample=adjust; else _audioSample=0; _audioseg++; // Next audio seg has audio ? // Compute new start time uint32_t starttime; if(!_videos[AUDIOSEG]._audiostream) { printf("No soundtrack\n"); *len=0; *samples=0; // _audioseg--; // Stay in a valid one to avoid crash later return 0; } starttime= _videos[AUDIOSEG]._aviheader->getTime (_segments[_audioseg]._start_frame); _videos[AUDIOSEG]._audiostream->goToTime(starttime); ; // Fresh start samuel printf("EditorPacket : switching to segment %lu\n",_audioseg); ret= getAudioPacket(dest, len, samples); if(adjust<0) { adjust=-adjust; if(adjust>_audioSample) _audioSample=0; else _audioSample-=adjust; } return ret; }
/** \fn parseMdia \brief Parse mdia header */ uint8_t MP4Header::parseMdia(void *ztom,uint32_t *trackType,uint32_t w, uint32_t h) { adm_atom *tom=(adm_atom *)ztom; ADMAtoms id; uint32_t container; uint32_t trackScale=_videoScale; uint32_t trackDuration; *trackType=TRACK_OTHER; uint8_t r=0; printf("<<Parsing Mdia>>\n"); while(!tom->isDone()) { adm_atom son(tom); if(!ADM_mp4SearchAtomName(son.getFCC(), &id,&container)) { adm_printf(ADM_PRINT_DEBUG,"[MDIA]Found atom %s unknown\n",fourCC::tostringBE(son.getFCC())); son.skipAtom(); continue; } switch(id) { case ADM_MP4_MDHD: { uint32_t version=son.read(),duration; son.skipBytes(3); // flags + version son.skipBytes(4); // creation time son.skipBytes(4); // mod time if(version==1) son.skipBytes(8); trackScale=son.read32(); // adm_printf(ADM_PRINT_DEBUG,"MDHD,Trackscale in mdhd:%u\n",trackScale); if(!trackScale) trackScale=600; // default duration=son.read32(); adm_printf(ADM_PRINT_DEBUG,"MDHD,duration in mdhd:%u (unscaled)\n",duration); duration=(uint32_t)((duration*1000.)/trackScale); adm_printf(ADM_PRINT_DEBUG,"MDHD,duration in mdhd:%u (scaled ms)\n",duration); trackDuration=duration; printf("MDHD,Track duration :%s, trackScale :%u\n",ms2timedisplay((1000*duration)/trackScale),trackScale); break; } case ADM_MP4_HDLR: { uint32_t type; son.read32(); son.read32(); type=son.read32(); printf("[HDLR]\n"); switch(type) { case MKFCCR('v','i','d','e')://'vide': *trackType=TRACK_VIDEO; printf("hdlr video found \n "); _movieDuration=trackDuration; _videoScale=trackScale; break; case MKFCCR('s','o','u','n'): //'soun': *trackType=TRACK_AUDIO; printf("hdlr audio found \n "); break; case MKFCCR('u','r','l',' ')://'url ': { int s; son.read32(); son.read32(); son.read32(); s=son.read(); char str[s+1]; son.readPayload((uint8_t *)str,s); str[s]=0; printf("Url : <%s>\n",str); } break; } break; } case ADM_MP4_MINF: { // We are only interested in stbl while(!son.isDone()) { adm_atom grandson(&son); if(!ADM_mp4SearchAtomName(grandson.getFCC(), &id,&container)) { adm_printf(ADM_PRINT_DEBUG,"[MINF]Found atom %s unknown\n",fourCC::tostringBE(son.getFCC())); grandson.skipAtom(); continue; } if(id==ADM_MP4_STBL) { if(! parseStbl(&grandson,*trackType, w, h,trackScale)) { printf("STBL failed\n"); return 0; } r=1; } grandson.skipAtom(); } } break; default: adm_printf(ADM_PRINT_DEBUG,"** atom NOT HANDLED [%s] \n",fourCC::tostringBE(son.getFCC())); } son.skipAtom(); } return r; }
void DIA_encoding::updateUI(void) { uint32_t tim; ADM_assert(dialog); // // nb/total=timestart/totaltime -> total time =timestart*total/nb // // if(!_lastnb) return; tim=clock.getElapsedMS(); if(_lastTime > tim) return; if( tim < _nextUpdate) return ; _nextUpdate = tim+GUI_UPDATE_RATE; sprintf(string,"%lu",_lastnb); gtk_label_set_text(GTK_LABEL(WID(label_frame)),string); sprintf(string,"%lu",_total); gtk_label_set_text(GTK_LABEL(WID(label_totalframe)),string); // Average bitrate on the last second uint32_t sum=0,aquant=0,gsum; for(int i=0;i<_roundup;i++) { sum+=_bitrate[i].size; aquant+=_bitrate[i].quant; } aquant/=_roundup; sum=(sum*8)/1000; // Now compute global average bitrate float whole=_videoSize,second; second=_lastnb; second/=_fps1000; second*=1000; whole/=second; whole/=1000; whole*=8; gsum=(uint32_t)whole; setBitrate(sum,gsum); setQuantIn(aquant); // compute fps uint32_t deltaFrame, deltaTime; deltaTime=tim-_lastTime; deltaFrame=_lastnb-_lastFrame; _fps_average =(float)( deltaFrame*1000.0F / deltaTime ); sprintf(string,"%.2f",_fps_average); gtk_label_set_text(GTK_LABEL(WID(label_fps)),string); uint32_t hh,mm,ss; double framesLeft=(_total-_lastnb); ms2time(tim,&hh,&mm,&ss); sprintf(string,"%02d:%02d:%02d",hh,mm,ss); gtk_label_set_text(GTK_LABEL(WID(label_elapsed)),string); gtk_label_set_text(GTK_LABEL(WID(label_eta)), ms2timedisplay((uint32_t) floor(0.5 + deltaTime * framesLeft / deltaFrame))); // Check if we should move on to the next sample period if (tim >= _nextSampleStartTime + ETA_SAMPLE_PERIOD ) { _lastTime=_nextSampleStartTime; _lastFrame=_nextSampleStartFrame; _nextSampleStartTime=tim; _nextSampleStartFrame=0; } else if (tim >= _nextSampleStartTime && _nextSampleStartFrame == 0 ) { // Store current point for use later as the next sample period. // _nextSampleStartTime=tim; _nextSampleStartFrame=_lastnb; } // update progress bar float f=_lastnb; f=f/_total; if(tray) tray->setPercent((int)(f*100.)); gtk_progress_set_percentage(GTK_PROGRESS(WID(progressbar1)),(gfloat)f); sprintf(string,QT_TR_NOOP("%d%%"),(int)(100*f)); if(isQuiet()) printf("[Encoding]%s\n",string); gtk_progress_bar_set_text (GTK_PROGRESS_BAR(WID(progressbar1)), string); _totalSize=_audioSize+_videoSize; setSize(_totalSize>>20); setAudioSizeIn((_audioSize>>20)); setVideoSizeIn((_videoSize>>20)); UI_purge(); }