summaryrefslogtreecommitdiffstats
path: root/apps/samples/vrml/ffmpeg-server.invoked.scxml
diff options
context:
space:
mode:
Diffstat (limited to 'apps/samples/vrml/ffmpeg-server.invoked.scxml')
-rw-r--r--apps/samples/vrml/ffmpeg-server.invoked.scxml246
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 &gt;= 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 &amp;&amp;
+ _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 &amp;&amp;
+ _event.data.pathComponent[1] === 'movie' &amp;&amp;
+ _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