Browse Source

mp4 encoder animation test

David Sehnal 4 years ago
parent
commit
6ad80bf66b

+ 25 - 4
src/extensions/mp4-export/encoder.ts

@@ -1,5 +1,6 @@
 import * as HME from 'h264-mp4-encoder';
 import { canvasToBlob } from '../../mol-canvas3d/util';
+import { AnimateAssemblyUnwind } from '../../mol-plugin-state/animation/built-in';
 import { PluginContext } from '../../mol-plugin/context';
 
 export class Mp4Encoder {
@@ -8,7 +9,7 @@ export class Mp4Encoder {
         const pass = this.plugin.canvas3d!.getImagePass({
             transparentBackground: false,
             cameraHelper: { axes: { name: 'off', params: {} } },
-            multiSample: { mode: 'off', sampleLevel: 2 }, // { mode: 'on', sampleLevel: 2 },
+            multiSample: { mode: 'on', sampleLevel: 4 }, // { mode: 'on', sampleLevel: 2 },
             postprocessing: this.plugin.canvas3d!.props.postprocessing
         });
         return pass;
@@ -19,11 +20,13 @@ export class Mp4Encoder {
     }
 
     async generate() {
-        const w = 1024, h = 768;
+        // const w = 1024, h = 768;
+        const w = 1920, h = 1080;
 
         const encoder = await HME.createH264MP4Encoder();
         encoder.width = w;
         encoder.height = h;
+        encoder.frameRate = 30;
         encoder.initialize();
 
         console.log('creating image pass');
@@ -34,16 +37,31 @@ export class Mp4Encoder {
         canvas.height = h;
         const canvasCtx = canvas.getContext('2d')!;
 
+        const loop = this.plugin.animationLoop;
+
+        loop.stop();
+        loop.resetTime(0);
+
+        const durationMs = 3000;
+        const fps = encoder.frameRate;
+
+        await this.plugin.managers.animation.play(AnimateAssemblyUnwind, { durationInMs: 3000, playOnce: true, target: 'all' });
+
         const imageData: Uint8ClampedArray[] = [];
-        const N = 60;
+        const N = Math.ceil(durationMs / 1000 * fps);
+        const dt = durationMs / (N - 1);
         console.log({ w, h });
         for (let i = 0; i < N; i++) {
+
+            const t = i * dt;
+            await loop.tick(t, true);
+
             const image = pass.getImageData(w, h);
             if (i === 0) canvasCtx.putImageData(image, 0, 0);
 
             imageData.push(image.data);
             console.log(`frame ${i + 1}/${N}`);
-            await this.sleep();
+            // await this.sleep();
         }
 
         let ii = 0;
@@ -59,6 +77,9 @@ export class Mp4Encoder {
         console.log('encoded');
         encoder.delete();
 
+        await this.plugin.managers.animation.stop();
+        loop.start();
+
         return { movie: uint8Array, image: await canvasToBlob(canvas, 'png') };
     }
 

+ 3 - 3
src/mol-plugin-state/manager/animation.ts

@@ -87,14 +87,14 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana
         }
     }
 
-    play<P>(animation: PluginStateAnimation<P>, params: P) {
-        this.stop();
+    async play<P>(animation: PluginStateAnimation<P>, params: P) {
+        await this.stop();
         if (!this.map.has(animation.name)) {
             this.register(animation);
         }
         this.updateParams({ current: animation.name });
         this.updateCurrentParams(params);
-        this.start();
+        await this.start();
     }
 
     async tick(t: number, isSynchronous?: boolean) {

+ 2 - 2
src/mol-plugin/animation-loop.ts

@@ -23,8 +23,8 @@ export class PluginAnimationLoop {
         }
     }
 
-    resetTime() {
-        this.plugin.canvas3d?.resetTime(now());
+    resetTime(t: number = now()) {
+        this.plugin.canvas3d?.resetTime(t);
     }
 
     start() {