1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "SVTK_Recorder.h"
24 #include "SVTK_ImageWriter.h"
25 #include "SVTK_ImageWriterMgr.h"
27 #include <vtkObjectFactory.h>
28 #include <vtkObject.h>
29 #include <vtkCallbackCommand.h>
30 #include <vtkRenderWindow.h>
31 #include <vtkTimerLog.h>
32 #include <vtkWindowToImageFilter.h>
33 #include <vtkJPEGWriter.h>
34 #include <vtkImageData.h>
44 #include <QApplication>
48 //#include "utilities.h"
51 static int MYDEBUG = 0;
53 static int MYDEBUG = 0;
59 //----------------------------------------------------------------------------
62 GetNameJPEG(const std::string& thePreffix,
67 ostringstream aStream;
68 aStream<<thePreffix<<"_"<<setw(6)<<setfill('0')<<theIndex<<".jpeg";
69 theName = aStream.str();
73 //----------------------------------------------------------------------------
74 vtkCxxRevisionMacro(SVTK_Recorder,"$Revision$");
75 vtkStandardNewMacro(SVTK_Recorder);
78 //----------------------------------------------------------------------------
82 myState(SVTK_Recorder_Stop),
85 myProgressiveMode(true),
86 myUseSkippedFrames(true),
88 myCommand(vtkCallbackCommand::New()),
93 myFilter(vtkWindowToImageFilter::New()),
94 myWriterMgr(new SVTK_ImageWriterMgr),
96 myNameAVIMaker("jpeg2yuv")
98 myCommand->SetClientData(this);
99 myCommand->SetCallback(SVTK_Recorder::ProcessEvents);
103 //----------------------------------------------------------------------------
113 //----------------------------------------------------------------------------
116 ::CheckExistAVIMaker()
120 ostringstream aStream;
121 aStream<<"which "<<myNameAVIMaker<<" >& /dev/null";
122 std::string anAVIMakeCheck = aStream.str();
123 int iErr = system(anAVIMakeCheck.c_str());
129 //----------------------------------------------------------------------------
132 ::SetName(const char* theName)
138 SVTK_Recorder::Name() const
140 return myName.c_str();
144 //----------------------------------------------------------------------------
147 ::SetNbFPS(const double theNbFPS)
160 //----------------------------------------------------------------------------
163 ::SetQuality(int theQuality)
165 myQuality = theQuality;
176 //----------------------------------------------------------------------------
179 ::SetRenderWindow(vtkRenderWindow* theRenderWindow)
181 myRenderWindow = theRenderWindow;
188 return myRenderWindow;
192 //----------------------------------------------------------------------------
195 ::SetProgressiveMode(bool theProgressiveMode)
197 myProgressiveMode = theProgressiveMode;
202 ::GetProgressiveMode() const
204 return myProgressiveMode;
208 //----------------------------------------------------------------------------
211 ::SetUseSkippedFrames(bool theUseSkippedFrames)
213 myUseSkippedFrames = theUseSkippedFrames;
218 ::UseSkippedFrames() const
220 return myUseSkippedFrames;
224 //----------------------------------------------------------------------------
227 ::ErrorStatus() const
229 return myErrorStatus;
240 //----------------------------------------------------------------------------
243 ::ProcessEvents(vtkObject* vtkNotUsed(theObject),
244 unsigned long theEvent,
246 void* vtkNotUsed(theCallData))
248 if(vtkObject* anObj = reinterpret_cast<vtkObject*>(theClientData)){
249 if(SVTK_Recorder* aSelf = dynamic_cast<SVTK_Recorder*>(anObj)){
250 if(theEvent==vtkCommand::EndEvent){
251 if(aSelf->State() == SVTK_Recorder::SVTK_Recorder_Record){
260 //----------------------------------------------------------------------------
265 if(myState == SVTK_Recorder_Stop){
267 myState = SVTK_Recorder_Record;
268 myFilter->SetInput(myRenderWindow);
270 myNbWrittenFrames = 0;
271 myRenderWindow->RemoveObserver(myCommand);
272 myRenderWindow->AddObserver(vtkCommand::EndEvent,
275 myRenderWindow->Render();
281 //----------------------------------------------------------------------------
286 QApplication::setOverrideCursor( Qt::WaitCursor );
288 if(myState == SVTK_Recorder_Record){
294 if(myUseSkippedFrames)
297 myFrameIndexes.clear();
301 myState = SVTK_Recorder_Stop;
304 QApplication::restoreOverrideCursor();
308 //----------------------------------------------------------------------------
313 myPaused = myPaused ? 0 : 1;
314 if(myPaused && !myFrameIndexes.empty()){
315 myFrameIndexes.back() *= -1;
316 if(MYDEBUG) cout<<"SVTK_Recorder::Pause - myFrameIndexes.back() = "<<myFrameIndexes.back()<<endl;
321 //----------------------------------------------------------------------------
324 GetFrameIndex(double theStartTime,
327 double aTimeNow = vtkTimerLog::GetCurrentTime();
328 double aDelta = aTimeNow - theStartTime;
329 return int(aDelta*theFPS);
339 if(myFrameIndex < 0){
341 myTimeStart = vtkTimerLog::GetCurrentTime();
343 int aFrameIndex = GetFrameIndex(myTimeStart,myNbFPS);
344 if(aFrameIndex <= myFrameIndex)
347 // If there was a "pause" we correct the myTimeStart
348 int aLastFrameIndex = myFrameIndexes.back();
349 if(aLastFrameIndex < 0){
350 myFrameIndexes.back() = abs(myFrameIndexes.back());
351 double aPauseTime = fabs((double)(aFrameIndex - myFrameIndex - 1)) / myNbFPS;
353 cout<<"SVTK_Recorder::DoRecord - aFrameIndex = "<<aFrameIndex<<
354 "; aPauseTime = "<<aPauseTime<<endl;
355 myTimeStart += aPauseTime;
358 aFrameIndex = GetFrameIndex(myTimeStart,myNbFPS);
359 if(aFrameIndex <= myFrameIndex)
362 myFrameIndex = aFrameIndex;
365 myFrameIndexes.push_back(myFrameIndex);
366 if(MYDEBUG) cout<<"SVTK_Recorder::DoRecord - myFrameIndex = "<<myFrameIndex<<endl;
368 myRenderWindow->RemoveObserver(myCommand);
369 myFilter->Modified();
372 GetNameJPEG(myName,myFrameIndex,aName);
376 vtkImageData *anImageData = vtkImageData::New();
377 anImageData->DeepCopy(myFilter->GetOutput());
379 myWriterMgr->StartImageWriter(anImageData,aName,myProgressiveMode,myQuality);
382 myRenderWindow->AddObserver(vtkCommand::EndEvent,
388 //----------------------------------------------------------------------------
393 vtkImageData *anImageData = myFilter->GetOutput();
399 anImageData->UpdateInformation();
400 int *anExtent = anImageData->GetWholeExtent();
401 anImageData->SetUpdateExtent(anExtent[0], anExtent[1],
402 anExtent[2], anExtent[3],
404 anImageData->UpdateData();
408 //----------------------------------------------------------------------------
415 if(myFrameIndexes.size() < 2)
418 size_t anId = 0, anEnd = myFrameIndexes.size() - 1;
419 for(; anId < anEnd; anId++){
420 int aStartIndex = myFrameIndexes[anId];
424 int aFinishIndex = abs(myFrameIndexes[anId + 1]);
425 if(aStartIndex + 1 == aFinishIndex)
428 std::string anInitialName;
429 std::ostringstream aStream;
430 GetNameJPEG(myName,aStartIndex,anInitialName);
431 for(int anIndex = aStartIndex + 1; anIndex < aFinishIndex; anIndex++){
433 std::string anCurrentName;
434 GetNameJPEG(myName,anIndex,anCurrentName);
435 aStream<<"ln -s "<< anInitialName<<" "<<anCurrentName<<";";
436 if(anIndex + 1 < aFinishIndex)
440 std::string aString(aStream.str());
441 system(aString.c_str());
442 if(MYDEBUG) cout<<"SVTK_Recorder::AddSkippedFrames - "<<aString<<endl;
447 //----------------------------------------------------------------------------
453 std::ostringstream aStream;
454 aStream<<myNameAVIMaker<<
457 //" -f "<<int(myNbFPS)<<" "<<
458 " -f "<<myNbFPS<<" "<<
459 " -n "<<myNbWrittenFrames<<" "<<
460 " -j "<<myName<<"_\%06d.jpeg "<<
464 std::string aString(aStream.str());
465 myErrorStatus = system(aString.c_str());
467 if(MYDEBUG) cout<<"SVTK_Recorder::MakeFileAVI - "<<aString<<endl;
469 QFileInfo aFileInfo(myName.c_str());
470 QString aDirPath = aFileInfo.absoluteDir().path();
471 QString aBaseName = aFileInfo.fileName();
473 QString("(cd ") + aDirPath +
475 " | egrep '" + aBaseName + "_[0-9]*.jpeg'" +
479 if(MYDEBUG) cout<<"SVTK_Recorder::MakeFileAVI - "<<(const char*)aCommand.toLatin1()<<endl;
480 system((const char*)aCommand.toLatin1());