← Back to team overview

yade-dev team mailing list archive

[svn] r1901 - in trunk: . gui/qt3 py

 

Author: eudoxos
Date: 2009-07-29 11:17:45 +0200 (Wed, 29 Jul 2009)
New Revision: 1901

Modified:
   trunk/SConstruct
   trunk/gui/qt3/GLViewer.cpp
   trunk/gui/qt3/GLViewer.hpp
   trunk/gui/qt3/SnapshotEngine.cpp
   trunk/gui/qt3/qt.py
   trunk/py/utils.py
Log:
1. Add GLViewer::nextFrameSnapshotFilename to save frame in postDraw
2. Adjust SnapshotEngine to take advantage of that. This should solve https://bugs.launchpad.net/yade/+bug/396023
3. utils.encodeVideoFromFrames can take list of files (instead of just wildcard). Backwards-compatible.
4. scons doc skips debian/ directory (would mess up if deb package was build)



Modified: trunk/SConstruct
===================================================================
--- trunk/SConstruct	2009-07-29 08:23:29 UTC (rev 1900)
+++ trunk/SConstruct	2009-07-29 09:17:45 UTC (rev 1901)
@@ -210,7 +210,7 @@
 		else: print "Nothing to clean: %s."%buildDir
 		sys.argv.remove('clean')
 	if 'tags' in sys.argv:
-		cmd="ctags -R --extra=+q --fields=+n --exclude='.*' --exclude=doc --exclude=scons-local --exclude=include --exclude='*.so' --langmap=c++:+.inl,c++:+.tpp,c++:+.ipp"
+		cmd="ctags -R --extra=+q --fields=+n --exclude='.*' --exclude=doc --exclude=scons-local --exclude=include --exclude=debian --exclude='*.so' --langmap=c++:+.inl,c++:+.tpp,c++:+.ipp"
 		print cmd; os.system(cmd)
 		sys.argv.remove('tags')
 	if 'doc' in sys.argv:

Modified: trunk/gui/qt3/GLViewer.cpp
===================================================================
--- trunk/gui/qt3/GLViewer.cpp	2009-07-29 08:23:29 UTC (rev 1900)
+++ trunk/gui/qt3/GLViewer.cpp	2009-07-29 09:17:45 UTC (rev 1901)
@@ -606,6 +606,12 @@
 		}
 	}
 	QGLViewer::postDraw();
+	if(!nextFrameSnapshotFilename.empty()){
+		// save the snapshot
+		saveSnapshot(QString(nextFrameSnapshotFilename),/*overwrite*/ true);
+		// notify the caller that it is done already (probably not an atomic op :-|, though)
+		nextFrameSnapshotFilename.clear();
+	}
 }
 
 string GLViewer::getRealTimeString(){

Modified: trunk/gui/qt3/GLViewer.hpp
===================================================================
--- trunk/gui/qt3/GLViewer.hpp	2009-07-29 08:23:29 UTC (rev 1900)
+++ trunk/gui/qt3/GLViewer.hpp	2009-07-29 09:17:45 UTC (rev 1901)
@@ -89,6 +89,10 @@
 		void initFromDOMElement(const QDomElement& element);
 		int viewId;
 
+		// if defined, snapshot will be saved to this file right after being drawn and the string will be reset.
+		// this way the caller will be notified of the frame being saved successfully.
+		string nextFrameSnapshotFilename;
+
 		boost::posix_time::ptime getLastUserEvent();
 
 

Modified: trunk/gui/qt3/SnapshotEngine.cpp
===================================================================
--- trunk/gui/qt3/SnapshotEngine.cpp	2009-07-29 08:23:29 UTC (rev 1900)
+++ trunk/gui/qt3/SnapshotEngine.cpp	2009-07-29 09:17:45 UTC (rev 1901)
@@ -12,7 +12,14 @@
 	ostringstream fss; fss<<fileBase<<setw(4)<<setfill('0')<<counter++<<".png";
 	LOG_DEBUG("GL view #"<<viewNo<<" → "<<fss.str())
 	glv->setSnapshotFormat("PNG");
-	glv->saveSnapshot(QString(fss.str()),/*overwrite*/ true);
+	glv->nextFrameSnapshotFilename=fss.str();
+	// wait for the renderer to save the frame (will happen at next postDraw)
+	timespec t1,t2; t1.tv_sec=0; t1.tv_nsec=10000000; /* 10 ms */
+	long waiting=0;
+	while(!glv->nextFrameSnapshotFilename.empty()){
+		nanosleep(&t1,&t2);
+		if(((++waiting) % 1000)==0) LOG_WARN("Already waiting "<<waiting/100<<"s for snapshot to be saved. Something went wrong?");
+	}
 	savedSnapshots.push_back(fss.str());
 	usleep((long)(msecSleep*1000));
 }

Modified: trunk/gui/qt3/qt.py
===================================================================
--- trunk/gui/qt3/qt.py	2009-07-29 08:23:29 UTC (rev 1900)
+++ trunk/gui/qt3/qt.py	2009-07-29 09:17:45 UTC (rev 1901)
@@ -22,6 +22,7 @@
 	See makePlayerVideo for more documentation.
 	"""
 	import os
+	from yade import utils
 	# create primary view if none
 	if len(views())==0: View()
 	# remove existing SnaphotEngines

Modified: trunk/py/utils.py
===================================================================
--- trunk/py/utils.py	2009-07-29 08:23:29 UTC (rev 1900)
+++ trunk/py/utils.py	2009-07-29 09:17:45 UTC (rev 1901)
@@ -331,14 +331,29 @@
 		o.bodies[i].shape['diffuseColor']=color
 	return imported
 
-def encodeVideoFromFrames(wildcard,out,renameNotOverwrite=True,fps=24):
-	import pygst,sys,gobject,os
+def encodeVideoFromFrames(frameSpec,out,renameNotOverwrite=True,fps=24):
+	"""Create .ogg video from external image files.
+	
+	@param frameSpec If string, wildcard in format understood by GStreamer's multifilesrc plugin (e.g. '/tmp/frame-%04d.png'). If list or tuple, filenames to be encoded in given order.
+	@param out file to save video into
+	@param renameNotOverwrite if True, existing same-named video file will have ~[number] appended; will be overwritten otherwise.
+	@param fps Frames per second.
+	"""
+	import pygst,sys,gobject,os,tempfile,shutil
 	pygst.require("0.10")
 	import gst
 	if renameNotOverwrite and os.path.exists(out):
 		i=0;
 		while(os.path.exists(out+"~%d"%i)): i+=1
 		os.rename(out,out+"~%d"%i); print "Output file `%s' already existed, old file renamed to `%s'"%(out,out+"~%d"%i)
+	if frameSpec.__class__==list or frameSpec.__class__==tuple:
+		# create a new common prefix, symlink given files to prefix-%05d.png in their order, adjust wildcard, go ahead.
+		tmpDir=tempfile.mkdtemp()
+		for no,frame in enumerate(frameSpec):
+			os.symlink(frame,os.path.join(tmpDir,'%07d'%no))
+		wildcard=os.path.join(tmpDir,'%07d')
+	else:
+		tmpDir=None; wildcard=frameSpec
 	print "Encoding video from %s to %s"%(wildcard,out)
 	pipeline=gst.parse_launch('multifilesrc location="%s" index=0 caps="image/png,framerate=\(fraction\)%d/1" ! pngdec ! ffmpegcolorspace ! theoraenc sharpness=2 quality=63 ! oggmux ! filesink location="%s"'%(wildcard,fps,out))
 	bus=pipeline.get_bus()
@@ -348,7 +363,10 @@
 	pipeline.set_state(gst.STATE_PLAYING)
 	mainloop.run()
 	pipeline.set_state(gst.STATE_NULL); pipeline.get_state()
+	# remove symlinked frames, if any
+	if tmpDir: shutil.rmtree(tmpDir)
 
+
 def readParamsFromTable(tableFileLine=None,noTableOk=False,unknownOk=False,**kw):
 	"""
 	Read parameters from a file and assign them to __builtin__ variables.