1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SVTK_Recorder.h"
22 #include "SVTK_ImageWriter.h"
23 #include "SVTK_ImageWriterMgr.h"
25 #include <vtkObjectFactory.h>
26 #include <vtkObject.h>
27 #include <vtkCallbackCommand.h>
28 #include <vtkRenderWindow.h>
29 #include <vtkTimerLog.h>
30 #include <vtkWindowToImageFilter.h>
31 #include <vtkJPEGWriter.h>
32 #include <vtkImageData.h>
42 #include <QApplication>
46 //#include "utilities.h"
49 static int MYDEBUG = 0;
51 static int MYDEBUG = 0;
57 //----------------------------------------------------------------------------
60 GetNameJPEG(const std::string& thePreffix,
64 std::ostringstream aStream;
65 aStream<<thePreffix<<"_"<<setw(6)<<setfill('0')<<theIndex<<".jpeg";
66 theName = aStream.str();
70 //----------------------------------------------------------------------------
71 vtkStandardNewMacro(SVTK_Recorder);
74 //----------------------------------------------------------------------------
78 myState(SVTK_Recorder_Stop),
81 myProgressiveMode(true),
82 myUseSkippedFrames(true),
84 myCommand(vtkCallbackCommand::New()),
89 myFilter(vtkWindowToImageFilter::New()),
90 myWriterMgr(new SVTK_ImageWriterMgr),
92 myNameAVIMaker("jpeg2yuv")
94 myCommand->SetClientData(this);
95 myCommand->SetCallback(SVTK_Recorder::ProcessEvents);
99 //----------------------------------------------------------------------------
109 //----------------------------------------------------------------------------
112 ::CheckExistAVIMaker()
115 std::ostringstream aStream;
117 aStream<<"which "<<myNameAVIMaker<<" 2> /dev/null";
119 aStream<<"setlocal & set P2=.;%PATH% & (for %e in (%PATHEXT%) do @for %i in ("<<myNameAVIMaker<<"%e) do @if NOT \"%~$P2:i\"==\"\" exit /b 0) & exit /b 1";
121 std::string anAVIMakeCheck = aStream.str();
122 int iErr = system(anAVIMakeCheck.c_str());
128 //----------------------------------------------------------------------------
131 ::SetName(const char* theName)
137 SVTK_Recorder::Name() const
139 return myName.c_str();
143 //----------------------------------------------------------------------------
146 ::SetNbFPS(const double theNbFPS)
159 //----------------------------------------------------------------------------
162 ::SetQuality(int theQuality)
164 myQuality = theQuality;
175 //----------------------------------------------------------------------------
178 ::SetRenderWindow(vtkRenderWindow* theRenderWindow)
180 myRenderWindow = theRenderWindow;
187 return myRenderWindow;
191 //----------------------------------------------------------------------------
194 ::SetProgressiveMode(bool theProgressiveMode)
196 myProgressiveMode = theProgressiveMode;
201 ::GetProgressiveMode() const
203 return myProgressiveMode;
207 //----------------------------------------------------------------------------
210 ::SetUseSkippedFrames(bool theUseSkippedFrames)
212 myUseSkippedFrames = theUseSkippedFrames;
217 ::UseSkippedFrames() const
219 return myUseSkippedFrames;
223 //----------------------------------------------------------------------------
226 ::ErrorStatus() const
228 return myErrorStatus;
239 //----------------------------------------------------------------------------
242 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
243 unsigned long theEvent,
245 void* vtkNotUsed(theCallData))
247 if(vtkObject* anObj = reinterpret_cast<vtkObject*>(theClientData)){
248 if(SVTK_Recorder* aSelf = dynamic_cast<SVTK_Recorder*>(anObj)){
249 if(theEvent==vtkCommand::EndEvent){
250 if(aSelf->State() == SVTK_Recorder::SVTK_Recorder_Record){
259 //----------------------------------------------------------------------------
264 if(myState == SVTK_Recorder_Stop){
266 myState = SVTK_Recorder_Record;
267 myFilter->SetInput(myRenderWindow);
269 myNbWrittenFrames = 0;
270 myRenderWindow->RemoveObserver(myCommand);
271 myRenderWindow->AddObserver(vtkCommand::EndEvent,
274 myRenderWindow->Render();
280 //----------------------------------------------------------------------------
285 QApplication::setOverrideCursor( Qt::WaitCursor );
287 if(myState == SVTK_Recorder_Record){
293 if(myUseSkippedFrames)
296 myFrameIndexes.clear();
300 myState = SVTK_Recorder_Stop;
303 QApplication::restoreOverrideCursor();
307 //----------------------------------------------------------------------------
312 myPaused = myPaused ? 0 : 1;
313 if(myPaused && !myFrameIndexes.empty()){
314 myFrameIndexes.back() *= -1;
315 if(MYDEBUG) cout<<"SVTK_Recorder::Pause - myFrameIndexes.back() = "<<myFrameIndexes.back()<<endl;
320 //----------------------------------------------------------------------------
323 GetFrameIndex(double theStartTime,
326 double aTimeNow = vtkTimerLog::GetUniversalTime();
327 double aDelta = aTimeNow - theStartTime;
328 return int(aDelta*theFPS);
338 if(myFrameIndex < 0){
340 myTimeStart = vtkTimerLog::GetUniversalTime();
342 int aFrameIndex = GetFrameIndex(myTimeStart,myNbFPS);
343 if(aFrameIndex <= myFrameIndex)
346 // If there was a "pause" we correct the myTimeStart
347 int aLastFrameIndex = myFrameIndexes.back();
348 if(aLastFrameIndex < 0){
349 myFrameIndexes.back() = abs(myFrameIndexes.back());
350 double aPauseTime = fabs((double)(aFrameIndex - myFrameIndex - 1)) / myNbFPS;
352 cout<<"SVTK_Recorder::DoRecord - aFrameIndex = "<<aFrameIndex<<
353 "; aPauseTime = "<<aPauseTime<<endl;
354 myTimeStart += aPauseTime;
357 aFrameIndex = GetFrameIndex(myTimeStart,myNbFPS);
358 if(aFrameIndex <= myFrameIndex)
361 myFrameIndex = aFrameIndex;
364 myFrameIndexes.push_back(myFrameIndex);
365 if(MYDEBUG) cout<<"SVTK_Recorder::DoRecord - myFrameIndex = "<<myFrameIndex<<endl;
367 myRenderWindow->RemoveObserver(myCommand);
368 myFilter->Modified();
371 GetNameJPEG(myName,myFrameIndex,aName);
375 vtkImageData *anImageData = vtkImageData::New();
376 anImageData->DeepCopy(myFilter->GetOutput());
378 myWriterMgr->StartImageWriter(myFilter,anImageData,aName,myProgressiveMode,myQuality);
381 myRenderWindow->AddObserver(vtkCommand::EndEvent,
387 //----------------------------------------------------------------------------
392 vtkImageData *anImageData = myFilter->GetOutput();
398 myFilter->UpdateInformation();
399 myFilter->SetUpdateExtentToWholeExtent();
404 //----------------------------------------------------------------------------
411 if(myFrameIndexes.size() < 2)
414 size_t anId = 0, anEnd = myFrameIndexes.size() - 1;
415 for(; anId < anEnd; anId++){
416 int aStartIndex = myFrameIndexes[anId];
420 int aFinishIndex = abs(myFrameIndexes[anId + 1]);
421 if(aStartIndex + 1 == aFinishIndex)
424 std::string anInitialName;
425 std::ostringstream aStream;
426 GetNameJPEG(myName,aStartIndex,anInitialName);
427 for(int anIndex = aStartIndex + 1; anIndex < aFinishIndex; anIndex++){
429 std::string anCurrentName;
430 GetNameJPEG(myName,anIndex,anCurrentName);
432 aStream<<"ln -s "<< anInitialName<<" "<<anCurrentName<<";";
434 aStream<<"COPY /Y "<<QString::fromStdString(anInitialName).replace("/","\\\\").toStdString()<<
435 " "<<QString::fromStdString(anCurrentName).replace("/","\\\\").toStdString()<<" > NUL";
437 if(anIndex + 1 < aFinishIndex)
445 std::string aString(aStream.str());
446 system(aString.c_str());
447 if(MYDEBUG) cout<<"SVTK_Recorder::AddSkippedFrames - "<<aString<<endl;
452 //----------------------------------------------------------------------------
458 std::ostringstream aStream;
459 aStream<<myNameAVIMaker<<
462 //" -f "<<int(myNbFPS)<<" "<<
463 " -f "<<myNbFPS<<" "<<
464 " -n "<<myNbWrittenFrames<<" "<<
465 " -j \""<<myName<<"_\%06d.jpeg\" "<<
466 "| yuv2lav"<<" -o \""<<myName<<"\"";
470 std::string aString(aStream.str());
471 myErrorStatus = system(aString.c_str());
473 if(MYDEBUG) cout<<"SVTK_Recorder::MakeFileAVI - "<<aString<<endl;
475 QFileInfo aFileInfo(myName.c_str());
476 QString aDirPath = aFileInfo.absoluteDir().path();
477 QString aBaseName = aFileInfo.fileName();
480 aCommand = QString("(cd ") + aDirPath +
482 " | egrep '" + aBaseName + "_[0-9]*.jpeg'" +
486 QString tmpFile = QString("_") + aBaseName + "_tempfile";
487 QString diskName = aDirPath.split("/")[0];
488 aCommand = diskName + " && (cd " + aDirPath.replace("/","\\\\") +
489 " && ((dir /b | findstr " + aBaseName + "_[0-9]*.jpeg > " + tmpFile +
490 ") & (for /f %i in (" + tmpFile + ") do (del \"%i\")) & (del " + tmpFile + "))) > NUL";
493 if(MYDEBUG) cout<<"SVTK_Recorder::MakeFileAVI - "<<(const char*)aCommand.toLatin1()<<endl;
494 system((const char*)aCommand.toLatin1());