/** \fn initialize */ bool GUIPlayback::initialize(void) { firstPts=admPreview::getCurrentPts(); if(getPreviewMode()==ADM_PREVIEW_NONE) // copy { videoChain=createEmptyVideoFilterChain(firstPts,1000*1000*1000*1000LL); }else { videoChain=createVideoFilterChain(firstPts,1000*1000*1000*1000LL); } if(!videoChain) { ADM_warning("Cannot create video chain\n"); return false; } int nb=videoChain->size(); videoFilter=(*videoChain)[nb-1]; FilterInfo *info=videoFilter->getInfo(); renderZoom zoom=ZOOM_AUTO; // if the video output has same width/height as input, we keep the same zoom aviInfo originalVideo; video_body->getVideoInfo(&originalVideo); renderZoom currentZoom=admPreview::getCurrentZoom(); if(info->width==originalVideo.width && info->height==originalVideo.height) zoom=currentZoom; // admPreview::setMainDimension(info->width,info->height,zoom); initializeAudio(); return true; }
/** \fn GUI_PlayAvi \brief MainLoop for internal movie playback */ void GUI_PlayAvi(void) { uint32_t framelen,flags; uint32_t max,err; uint64_t oldTimeFrame; aviInfo info; renderZoom oldZoom=admPreview::getCurrentZoom(); video_body->getVideoInfo(&info); // check we got everything... if (!video_body->getNbSegment()) return; if (playing) { stop_req = 1; return; } oldTimeFrame=admPreview::getCurrentPts(); uint32_t priorityLevel; #ifndef __HAIKU__ originalPriority = getpriority(PRIO_PROCESS, 0); prefs->get(PRIORITY_PLAYBACK,&priorityLevel); setpriority(PRIO_PROCESS, 0, ADM_getNiceValue(priorityLevel)); #endif stop_req = 0; playing = 1; admPreview::deferDisplay(true); //admPreview::samePicture(); GUIPlayback *playLoop=new GUIPlayback; playLoop->initialize(); playLoop->run(); delete playLoop; playing = 0; admPreview::deferDisplay(false); // Resize the output window to original size... ADM_info("Restoring display.\n"); admPreview::setMainDimension(info.width,info.height,oldZoom); // If we are processing the video, the current time // might not be matching a source video time => PROBLEM // Go back to the beginning to be on safe ground // In copy mode, we can keep the current position if(getPreviewMode()!=ADM_PREVIEW_NONE) admPreview::seekToTime(oldTimeFrame); UI_purge(); admPreview::samePicture(); GUI_setCurrentFrameAndTime(); UI_purge(); }
/** \fn initialize */ bool GUIPlayback::initialize(void) { firstPts=admPreview::getCurrentPts(); if(getPreviewMode()==ADM_PREVIEW_NONE) // copy { videoChain=createEmptyVideoFilterChain(firstPts,1000*1000*1000*1000LL); }else { videoChain=createVideoFilterChain(firstPts,1000*1000*1000*1000LL); } if(!videoChain) { ADM_warning("Cannot create video chain\n"); return false; } int nb=videoChain->size(); videoFilter=(*videoChain)[nb-1]; FilterInfo *info=videoFilter->getInfo(); admPreview::setMainDimension(info->width,info->height,ZOOM_AUTO); initializeAudio(); return true; }
//static uint8_t Vbuffer[7.0*5.6*3]; //AVDMGenericVideoStream *getFirstVideoFilter( void) // //_____________________________________________________________ void GUI_PlayAvi(bool forceStop) { uint32_t time_e, time_a = 0; uint32_t err = 0, acc = 0; uint32_t max; uint32_t framelen,flags; AVDMGenericVideoStream *filter; vids = 0, auds = 0, dauds = 0; // check we got everything... if (!avifileinfo) return; if((curframe+1)>= avifileinfo->nb_frames-1) { printf("No frame left\n"); return; } if (avifileinfo->fps1000 == 0) return; if (playing || forceStop) { stop_req = 1; return; } uint32_t priorityLevel; originalPriority = getpriority(PRIO_PROCESS, 0); prefs->get(PRIORITY_PLAYBACK,&priorityLevel); setpriority(PRIO_PROCESS, 0, ADM_getNiceValue(priorityLevel)); uint32_t played_frame=0; uint32_t remaining=avifileinfo->nb_frames-curframe; if(getPreviewMode()==ADM_PREVIEW_OUTPUT) { filter=getLastVideoFilter(curframe,remaining); } else { filter=getFirstVideoFilter(curframe,remaining ); } max=filter->getInfo()->nb_frames; // compute how much a frame lasts in ms one_frame = (uint32_t) floor(1000.*1000.*10. / filter->getInfo()->fps1000); err = one_frame % 10; one_frame /= 10; // Duration of a frame in ms, err =leftover in 1/10 ms // go to RealTime... printf("One frame : %lu, err=%lu ms\n", one_frame, err); // prepare 1st frame stop_req = 0; playing = 1; #ifdef HAVE_AUDIO ComputePreload(); #endif //renderStartPlaying(); // reset timer reference resetTime(); admPreview::deferDisplay(1,curframe); admPreview::update(played_frame); do { vids++; admPreview::displayNow(played_frame);; update_status_bar(); if (time_a == 0) time_a = getTime(0); // mark ! //printf("\n Rendering %lu frame\n",curframe); // read frame in chunk if((played_frame)>=(max-1)) { printf("\nEnd met (%lu / %lu )\n",played_frame,max); goto abort_play; } admPreview::update(played_frame+1);; curframe++; played_frame++; #ifdef HAVE_AUDIO FillAudio(); #endif time_e = getTime(1); acc += err; if (acc > 10) { acc -= 10; time_a++; } time_a += one_frame; // delta a is next frame time // time is is current time delta = time_a - time_e; if (delta <= 0) { //if(delta<-19) // allow 19 ms late without warning... // tick seems to be ~ 18 ms //printf("\n Late ....,due : %lu ms / found : %lu \n", // time_a,time_e); // a call to whatever sleep function will last at leat 10 ms // give some time to GTK } else { // a call to whatever sleep function will last at leat 10 ms // give some time to GTK if (delta > 10) GUI_Sleep(delta - 10); } // UI_purge(); if(getPreviewMode()==ADM_PREVIEW_SEPARATE ) { UI_purge(); UI_purge(); } } while (!stop_req); abort_play: // ___________________________________ // Flush buffer // go back to normal display mode //____________________________________ playing = 0; getFirstVideoFilter( ); admPreview::deferDisplay(0,0); UI_purge(); // Updated by expose ? admPreview::update(curframe); UI_purge(); update_status_bar(); #ifdef HAVE_AUDIO if (currentaudiostream) { if (wavbuf) ADM_dealloc(wavbuf); deleteAudioFilter(NULL); currentaudiostream->endDecompress(); AVDM_AudioClose(); } #endif // done. setpriority(PRIO_PROCESS, 0, originalPriority); };
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; } }