瀏覽代碼

feat: support requestVideoFrameCallback

hujinliang 4 年之前
父節點
當前提交
276dd751e8
共有 6 個文件被更改,包括 109 次插入60 次删除
  1. 38 13
      web/dist/vap.js
  2. 0 0
      web/dist/vap.min.js
  3. 2 1
      web/dist/video.d.ts
  4. 34 34
      web/dist/webgl-render-vap.d.ts
  5. 30 8
      web/src/video.ts
  6. 5 4
      web/src/webgl-render-vap.ts

+ 38 - 13
web/dist/vap.js

@@ -1324,10 +1324,12 @@
         precache: false,
         // 是否静音播放
         mute: false,
-        config: ''
+        config: '',
+        accurate: false
       }, options);
       this.fps = 20;
       this.setBegin = true;
+      this.useFrameCallback = false;
       this.requestAnim = this.requestAnimFunc();
       this.container = this.options.container;
 
@@ -1418,6 +1420,10 @@
 
           document.body.appendChild(this.video);
           video.load();
+        }
+
+        if ('requestVideoFrameCallback' in this.video) {
+          this.useFrameCallback = !!this.options.accurate;
         } // 绑定事件
 
 
@@ -1428,9 +1434,15 @@
       }
     }, {
       key: "drawFrame",
-      value: function drawFrame() {
-        this._drawFrame = this._drawFrame || this.drawFrame.bind(this);
-        this.animId = this.requestAnim(this._drawFrame);
+      value: function drawFrame(_, info) {
+        this._drawFrame = this._drawFrame || this.drawFrame.bind(this, _, info);
+
+        if (this.useFrameCallback) {
+          // @ts-ignore
+          this.animId = this.video.requestVideoFrameCallback(this.drawFrame.bind(this));
+        } else {
+          this.animId = this.requestAnim(this._drawFrame);
+        }
       }
     }, {
       key: "play",
@@ -1494,21 +1506,27 @@
     }, {
       key: "cancelRequestAnimation",
       value: function cancelRequestAnimation() {
-        if (window.cancelAnimationFrame) {
+        if (this.useFrameCallback) {
+          try {
+            // @ts-ignore
+            this.video.cancelVideoFrameCallback(this.animId);
+          } catch (e) {}
+        } else if (window.cancelAnimationFrame) {
           cancelAnimationFrame(this.animId);
+        } else {
+          clearTimeout(this.animId);
         }
-
-        clearTimeout(this.animId);
       }
     }, {
       key: "destroy",
       value: function destroy() {
+        this.cancelRequestAnimation();
+
         if (this.video) {
           this.video.parentNode && this.video.parentNode.removeChild(this.video);
           this.video = null;
         }
 
-        this.cancelRequestAnimation();
         this.options.onDestory && this.options.onDestory();
       }
     }, {
@@ -1530,7 +1548,13 @@
       value: function onplaying() {
         if (!this.firstPlaying) {
           this.firstPlaying = true;
-          this.drawFrame();
+
+          if (this.useFrameCallback) {
+            // @ts-ignore
+            this.animId = this.video.requestVideoFrameCallback(this.drawFrame.bind(this));
+          } else {
+            this.drawFrame(null, null);
+          }
         }
       }
     }, {
@@ -1830,13 +1854,13 @@
       }
     }, {
       key: "drawFrame",
-      value: function drawFrame() {
+      value: function drawFrame(_, info) {
         var _this2 = this;
 
         var gl = this.instance.gl;
 
         if (!gl) {
-          get(getPrototypeOf$1(WebglRenderVap.prototype), "drawFrame", this).call(this);
+          get(getPrototypeOf$1(WebglRenderVap.prototype), "drawFrame", this).call(this, _, info);
 
           return;
         }
@@ -1844,7 +1868,8 @@
         gl.clear(gl.COLOR_BUFFER_BIT);
 
         if (this.vapFrameParser) {
-          var frame = Math.floor(this.video.currentTime * this.options.fps);
+          var timePoint = info && info.mediaTime >= 0 ? info.mediaTime : this.video.currentTime;
+          var frame = Math.floor(timePoint * this.options.fps);
           var frameData = this.vapFrameParser.getFrame(frame);
           var posArr = [];
 
@@ -1884,7 +1909,7 @@
 
         gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
 
-        get(getPrototypeOf$1(WebglRenderVap.prototype), "drawFrame", this).call(this);
+        get(getPrototypeOf$1(WebglRenderVap.prototype), "drawFrame", this).call(this, _, info);
       }
     }, {
       key: "destroy",

文件差異過大導致無法顯示
+ 0 - 0
web/dist/vap.min.js


+ 2 - 1
web/dist/video.d.ts

@@ -10,11 +10,12 @@ export default class VapVideo {
     private events;
     private _drawFrame;
     private animId;
+    private useFrameCallback;
     private firstPlaying;
     private setBegin;
     precacheSource(source: any): Promise<string>;
     initVideo(): void;
-    drawFrame(): void;
+    drawFrame(_: any, info: any): void;
     play(): void;
     pause(): void;
     setTime(t: any): void;

+ 34 - 34
web/dist/webgl-render-vap.d.ts

@@ -1,34 +1,34 @@
-import { VapConfig } from "./type";
-import VapVideo from './video';
-export default class WebglRenderVap extends VapVideo {
-    constructor(options: VapConfig);
-    private insType;
-    private textures;
-    private buffers;
-    private shaders;
-    private vapFrameParser;
-    private resources;
-    private instance;
-    private program;
-    private videoTexture;
-    private aPosition;
-    private aTexCoord;
-    private aAlphaTexCoord;
-    private _imagePos;
-    init(): Promise<void>;
-    setCanvas(): void;
-    initWebGL(): any;
-    /**
-     * 顶点着色器
-     */
-    initVertexShader(): any;
-    /**
-     * 片元着色器
-     */
-    initFragmentShader(): any;
-    initTexture(): void;
-    initVideoTexture(): void;
-    drawFrame(): void;
-    destroy(): void;
-    clearMemoryCache(): void;
-}
+import { VapConfig } from "./type";
+import VapVideo from './video';
+export default class WebglRenderVap extends VapVideo {
+    constructor(options: VapConfig);
+    private insType;
+    private textures;
+    private buffers;
+    private shaders;
+    private vapFrameParser;
+    private resources;
+    private instance;
+    private program;
+    private videoTexture;
+    private aPosition;
+    private aTexCoord;
+    private aAlphaTexCoord;
+    private _imagePos;
+    init(): Promise<void>;
+    setCanvas(): void;
+    initWebGL(): any;
+    /**
+     * 顶点着色器
+     */
+    initVertexShader(): any;
+    /**
+     * 片元着色器
+     */
+    initFragmentShader(): any;
+    initTexture(): void;
+    initVideoTexture(): void;
+    drawFrame(_: any, info: any): void;
+    destroy(): void;
+    clearMemoryCache(): void;
+}

+ 30 - 8
web/src/video.ts

@@ -37,12 +37,14 @@ export default class VapVideo {
         precache: false,
         // 是否静音播放
         mute: false,
-        config: ''
+        config: '',
+        accurate: false
       },
       options
     );
     this.fps = 20;
     this.setBegin = true;
+    this.useFrameCallback = false;
     this.requestAnim = this.requestAnimFunc();
     this.container = this.options.container;
     if (!this.options.src || !this.options.config || !this.options.container) {
@@ -61,6 +63,7 @@ export default class VapVideo {
   private events;
   private _drawFrame: Function;
   private animId: number;
+  private useFrameCallback: boolean;
   private firstPlaying: boolean;
   private setBegin: boolean;
 
@@ -133,15 +136,23 @@ export default class VapVideo {
       document.body.appendChild(this.video);
       video.load();
     }
+    if ( 'requestVideoFrameCallback' in this.video ) {
+      this.useFrameCallback = !!this.options.accurate;
+    }
     // 绑定事件
     this.events = {}
     ;['playing', 'pause', 'ended', 'error', 'canplay'].forEach(item => {
       this.on(item, this['on' + item].bind(this));
     })
   }
-  drawFrame() {
-    this._drawFrame = this._drawFrame || this.drawFrame.bind(this);
-    this.animId = this.requestAnim(this._drawFrame);
+  drawFrame(_, info) {
+    this._drawFrame = this._drawFrame || this.drawFrame.bind(this, _, info);
+    if ( this.useFrameCallback ) {
+      // @ts-ignore
+      this.animId = this.video.requestVideoFrameCallback( this.drawFrame.bind(this) );
+    } else {
+      this.animId = this.requestAnim(this._drawFrame);
+    }
   }
 
   play() {
@@ -193,18 +204,24 @@ export default class VapVideo {
   }
 
   cancelRequestAnimation() {
-    if (window.cancelAnimationFrame) {
+    if (this.useFrameCallback) {
+      try {
+        // @ts-ignore
+        this.video.cancelVideoFrameCallback(this.animId);
+      } catch (e) {}
+    }else if (window.cancelAnimationFrame) {
       cancelAnimationFrame(this.animId);
+    } else {
+      clearTimeout(this.animId);
     }
-    clearTimeout(this.animId);
   }
 
   destroy() {
+    this.cancelRequestAnimation();
     if (this.video) {
       this.video.parentNode && this.video.parentNode.removeChild(this.video);
       this.video = null
     }
-    this.cancelRequestAnimation();
     this.options.onDestory && this.options.onDestory();
   }
 
@@ -223,7 +240,12 @@ export default class VapVideo {
   onplaying() {
     if (!this.firstPlaying) {
       this.firstPlaying = true;
-      this.drawFrame()
+      if ( this.useFrameCallback ) {
+        // @ts-ignore
+        this.animId = this.video.requestVideoFrameCallback( this.drawFrame.bind(this) );
+      } else {
+        this.drawFrame(null, null)
+      }
     }
   }
 

+ 5 - 4
web/src/webgl-render-vap.ts

@@ -279,15 +279,16 @@ export default class WebglRenderVap extends VapVideo {
     gl.vertexAttribPointer(this.aAlphaTexCoord, 2, gl.FLOAT, false, size * 6, size * 4); // rgb像素位置
   }
 
-  drawFrame() {
+  drawFrame(_, info) {
     const gl = this.instance.gl;
     if (!gl) {
-      super.drawFrame();
+      super.drawFrame(_, info);
       return
     }
     gl.clear(gl.COLOR_BUFFER_BIT);
     if (this.vapFrameParser) {
-      const frame = Math.floor(this.video.currentTime * this.options.fps);
+      const timePoint = (info && info.mediaTime >= 0) ? info.mediaTime : this.video.currentTime
+      const frame = Math.floor(timePoint * this.options.fps);
       const frameData = this.vapFrameParser.getFrame(frame);
       let posArr = [];
 
@@ -312,7 +313,7 @@ export default class WebglRenderVap extends VapVideo {
     }
     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, this.video); // 指定二维纹理方式
     gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
-    super.drawFrame();
+    super.drawFrame(_, info);
   }
 
   destroy() {

部分文件因文件數量過多而無法顯示