diff options
Diffstat (limited to 'apps/samples/vrml/ffmpeg-server.invoked.scxml')
-rw-r--r-- | apps/samples/vrml/ffmpeg-server.invoked.scxml | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/apps/samples/vrml/ffmpeg-server.invoked.scxml b/apps/samples/vrml/ffmpeg-server.invoked.scxml new file mode 100644 index 0000000..bac0792 --- /dev/null +++ b/apps/samples/vrml/ffmpeg-server.invoked.scxml @@ -0,0 +1,246 @@ +<scxml datamodel="ecmascript"> + <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" /> + + <script> +//<![CDATA[ + function clone(item) { + if (!item) { return item; } // null, undefined values check + + var types = [ Number, String, Boolean ], + result; + + // normalizing primitives if someone did new String('aaa'), or new Number('444'); + types.forEach(function(type) { + if (item instanceof type) { + result = type( item ); + } + }); + + if (typeof result == "undefined") { + if (Object.prototype.toString.call( item ) === "[object Array]") { + result = []; + item.forEach(function(child, index, array) { + result[index] = clone( child ); + }); + } else if (typeof item == "object") { + // testing that this is DOM + if (item.nodeType && typeof item.cloneNode == "function") { + var result = item.cloneNode( true ); + } else if (!item.prototype) { // check that this is a literal + if (item instanceof Date) { + result = new Date(item); + } else { + // it is an object literal + result = {}; + for (var i in item) { + result[i] = clone( item[i] ); + } + } + } else { + // depending what you would like here, + // just keep the reference, or create new object + if (false && item.constructor) { + // would not advice to do that, reason? Read below + result = new item.constructor(); + } else { + result = item; + } + } + } else { + result = item; + } + } + + return result; + } +//]]> + </script> + + <datamodel> + <data id="modelDir" /> + <data id="requests">{}</data> + </datamodel> + + <state id="start"> + <onentry> + <log expr="modelDir" /> + </onentry> + <invoke type="osgconvert" id="osgvonvert.frame"> + <param name="threads" expr="1" /> + <finalize> + <script> + requests[_event.data.context].job.renderedFrames++; + </script> + <!-- osgconverter will copy its send request for the reply so these are still available --> + <send target="#_ffmpeg" event="render.frame"> + <param name="frame" expr="_event.data.content.bmp" /> + <param name="context" expr="_event.data.context" /> + </send> + <if cond="requests[_event.data.context].job.renderedFrames >= requests[_event.data.context].job.totalFrames"> + <send target="#_ffmpeg" event="render.end"> + <param name="context" expr="_event.data.context" /> + </send> + </if> + </finalize> + </invoke> + + <invoke type="ffmpeg" id="ffmpeg"> + <finalize> + <script> +// dump(_event); + </script> + <send target="#_parent" event="render.done"> + <param name="context" expr="_event.data.context" /> + <param name="movie" expr="_event.data.movie" /> + <param name="mimetype" expr="_event.data.mimetype" /> + <param name="filename" expr="_event.data.filename" /> + </send> + <script> + // free up job in requests + requests[_event.data.context] = undefined; + </script> + + </finalize> + </invoke> + + <state id ="idle"> + <!-- <onentry> + <script> + print("Invokers:"); + dump(_invokers['ffmpeg']); + </script> + </onentry> --> + <transition event="http.post" target="idle" cond=" + _event.data.pathComponent.length == 2 && + _event.data.pathComponent[1] === 'movie'"> + <!-- + Something to encode just arrived. + Interpolate pose information and send each frame to the osg converter. + The finalize of the osgconverter will send the images to ffmpeg whose + finalize will trigger the response. + --> + <script> +//<![CDATA[ +// dump(_event); + var pathDelim = ':'; // we need to flatten directories - this will seperate them in filenames + + // store event + var job = {}; + job.event = _event; + job.framesPerSec = 25; + job.lengthInSec = _event.data.content.data.movieLength; + job.format = _event.data.content.data.format; + job.height = _event.data.content.data.height; + job.width = _event.data.content.data.width; + job.keyFrames = _event.data.content.data.frames; + job.frames = []; + job.totalFrames = job.lengthInSec * job.framesPerSec + job.renderedFrames = 0; + + // sanitize + if (job.height % 2) + job.height++; + if (job.width % 2) + job.width++; + + // calculate overall relative length + var totalRelLength = 0; + for (var index in job.keyFrames) { + totalRelLength += job.keyFrames[index].relFrameLength; + } + var framesToRelLength = job.totalFrames / totalRelLength; + + // create frames + for (var kfIndex = 0; job.keyFrames[kfIndex]; kfIndex++) { + var nextPose = false; + if (job.keyFrames[kfIndex + 1]) { + nextPose = job.keyFrames[kfIndex + 1].pose; + } + var keyFrame = job.keyFrames[kfIndex]; + + keyFrame.modelFile = keyFrame.imageURL.substr(keyFrame.serverURL.length + 1); + keyFrame.file = keyFrame.modelFile.substr(0, keyFrame.modelFile.indexOf('.')); + keyFrame.ext = keyFrame.modelFile.substr(keyFrame.modelFile.indexOf('.') + 1); + + keyFrame.modelFile = keyFrame.file + ".osgb"; + keyFrame.modelFile = keyFrame.modelFile.replace(/\//g, pathDelim); + keyFrame.modelFile = modelDir + '/' + keyFrame.modelFile; + + var currentPose = keyFrame.pose; + var thisFrames = Math.round(keyFrame.relFrameLength * framesToRelLength); + var startTransitionAt = Math.round((100 - keyFrame.relTransitionLength) * 0.01 * thisFrames); + var transitionFrames = thisFrames - startTransitionAt; + + //print("---------------------\n"); + //print("lengthInSec: " + job.lengthInSec + "\n"); + //print("totalFrames: " + job.totalFrames + "\n"); + //print("thisFrames for " + kfIndex + ": " + thisFrames + "\n"); + //print("startTransitionAt for " + kfIndex + ": " + startTransitionAt + "\n"); + //print("transitionFrames for " + kfIndex + ": " + transitionFrames + "\n"); + + for (var frameIndex = 0; frameIndex < thisFrames && job.frames.length <= job.totalFrames; frameIndex++) { + var frame = clone(keyFrame); + + if (frameIndex > startTransitionAt && nextPose) { + + var transitionProgress = (frameIndex - startTransitionAt) / transitionFrames; + frame.pose.pitch += (nextPose.pitch - frame.pose.pitch) * transitionProgress; + frame.pose.roll += (nextPose.roll - frame.pose.roll) * transitionProgress; + frame.pose.yaw += (nextPose.yaw - frame.pose.yaw) * transitionProgress; + frame.pose.x += (nextPose.x - frame.pose.x) * transitionProgress; + frame.pose.y += (nextPose.y - frame.pose.y) * transitionProgress; + frame.pose.z += (nextPose.z - frame.pose.z) * transitionProgress; + frame.pose.zoom += (nextPose.zoom - frame.pose.zoom) * transitionProgress; + + //print("#########################\n"); + //print("Transition at: " + frameIndex + " \ Progress: " + transitionProgress + "\n"); + //print("Interpolated pose:\n") + //dump(frame.pose); + } + + job.frames.push(frame); + } + } + job.totalFrames = job.frames.length; + requests[_event.origin] = {}; + requests[_event.origin].job = job; +//]]> + </script> + <send target="#_ffmpeg" event="render.start" idlocation="requests[_event.origin].sendId"> + <param name="context" expr="_event.origin" /> + <param name="format" expr="requests[_event.origin].job.format" /> + <param name="width" expr="requests[_event.origin].job.width" /> + <param name="height" expr="requests[_event.origin].job.height" /> + </send> + <foreach array="requests[_event.origin].job.frames" item="frame" index="index"> + <send target="#_osgvonvert.frame"> + <param name="format" expr="'bmp'" /> + <!-- param name="dest" expr="'/Users/sradomski/Desktop/ctrl/' + index + '.bmp'" / --> + <param name="source" expr="frame.modelFile" /> + <param name="pitch" expr="frame.pose.pitch" /> + <param name="roll" expr="frame.pose.roll" /> + <param name="yaw" expr="frame.pose.yaw" /> + <param name="zoom" expr="frame.pose.zoom" /> + <param name="x" expr="frame.pose.x" /> + <param name="y" expr="frame.pose.y" /> + <param name="z" expr="frame.pose.z" /> + <param name="width" expr="requests[_event.origin].job.width" /> + <param name="height" expr="requests[_event.origin].job.height" /> + <param name="autorotate" expr="frame.pose.autorotate" /> + <param name="context" expr="_event.origin" /> + </send> + </foreach> + </transition> + + <transition event="http.get" target="idle" cond=" + _event.data.pathComponent.length == 3 && + _event.data.pathComponent[1] === 'movie' && + _event.data.pathComponent[2] === 'codecs'"> + <send target="#_parent" event="send.codecs"> + <param name="context" expr="_event.origin" /> + <param name="codecs" expr="_invokers['ffmpeg']" /> + </send> + </transition> + </state> + </state> +</scxml>
\ No newline at end of file |