Browse Source

新增H5页面

wuyongxiang 4 years ago
commit
ec45edf6a7
100 changed files with 33788 additions and 0 deletions
  1. 184 0
      application.properties
  2. 39 0
      logback-spring.xml
  3. 1770 0
      static/Player/Decoder.js
  4. 335 0
      static/Player/Player.js
  5. 551 0
      static/Player/YUVCanvas.js
  6. BIN
      static/Player/avc.wasm
  7. BIN
      static/avc.wasm
  8. 202 0
      static/css/home.css
  9. 331 0
      static/css/homeNew.css
  10. 1216 0
      static/css/index.css
  11. 13 0
      static/css/swiper-bundle.min.css
  12. 14 0
      static/css/swiper-bundle.min.js
  13. 400 0
      static/distss/WXdraw.js
  14. 291 0
      static/distss/draw.js
  15. BIN
      static/fonts/Gloss_And_Bloom.ttf
  16. BIN
      static/fonts/hei.ttf
  17. BIN
      static/img/anniu_icon.png
  18. BIN
      static/img/bangzu_icon.png
  19. BIN
      static/img/beijing_pic.png
  20. BIN
      static/img/expenienceCenter/anniu_icon.png
  21. BIN
      static/img/expenienceCenter/beijing_pic.png
  22. BIN
      static/img/expenienceCenter/beijing_pic2.png
  23. BIN
      static/img/expenienceCenter/bg.png
  24. BIN
      static/img/expenienceCenter/bg2.png
  25. BIN
      static/img/expenienceCenter/bg3.png
  26. BIN
      static/img/expenienceCenter/biankuang_shuoming_pic.png
  27. BIN
      static/img/expenienceCenter/biankuang_tiyanzhongxin_pic.png
  28. BIN
      static/img/expenienceCenter/biankuang_tubiao_pic.png
  29. BIN
      static/img/expenienceCenter/biaotikuang2_pic.png
  30. BIN
      static/img/expenienceCenter/biaotikuang_pic.png
  31. BIN
      static/img/expenienceCenter/you2_icon.png
  32. BIN
      static/img/expenienceCenter/you_icon.png
  33. BIN
      static/img/expenienceCenter/youimg.png
  34. BIN
      static/img/expenienceCenter/zuo2_icon.png
  35. BIN
      static/img/expenienceCenter/zuo_icon.png
  36. BIN
      static/img/goumai_icon.png
  37. BIN
      static/img/goumai_icon@2x.png
  38. BIN
      static/img/goumai_pic.png
  39. BIN
      static/img/home_icon.png
  40. BIN
      static/img/musicfalse.png
  41. BIN
      static/img/musicturn.png
  42. BIN
      static/img/shang_icon.png
  43. BIN
      static/img/svip_icon.png
  44. BIN
      static/img/tianjia_icon.png
  45. BIN
      static/img/tianjiashouji_pic.png
  46. BIN
      static/img/time.png
  47. BIN
      static/img/u760.jpg
  48. BIN
      static/img/vip_icon.png
  49. BIN
      static/img/wx/fanhui_icon.png
  50. BIN
      static/img/wx/gengduo_icon.png
  51. BIN
      static/img/wx/guanbi_icon.png
  52. BIN
      static/img/wx/home_icon.png
  53. BIN
      static/img/wx/jianqieban_icon.png
  54. BIN
      static/img/wx/shangchuan_icon.png
  55. BIN
      static/img/wx/tianjiashouji_pic.png
  56. BIN
      static/img/wx/tuichu_icon.png
  57. BIN
      static/img/xia_icon.png
  58. BIN
      static/img/xingdong_icon.png
  59. BIN
      static/img/xingyao_icon.png
  60. BIN
      static/img/xuanfu_icon.png
  61. 183 0
      static/js/AAC — Audiocogs.html
  62. 4655 0
      static/js/AAC — Audiocogs_files/aac.js
  63. 3 0
      static/js/AAC — Audiocogs_files/all.min.css
  64. 4003 0
      static/js/AAC — Audiocogs_files/aurora.js
  65. 83 0
      static/js/AAC — Audiocogs_files/auroraplayer.js
  66. 53 0
      static/js/AAC — Audiocogs_files/classlist.js
  67. BIN
      static/js/AAC — Audiocogs_files/fallback_album_art.png
  68. 283 0
      static/js/AAC — Audiocogs_files/player.css
  69. 363 0
      static/js/AAC — Audiocogs_files/player.js
  70. BIN
      static/js/AAC — Audiocogs_files/volume_high.png
  71. BIN
      static/js/AAC — Audiocogs_files/volume_low.png
  72. BIN
      static/js/AAC — Audiocogs_files/white-octocat.png
  73. BIN
      static/js/AAC — Audiocogs_files/white-twitter.png
  74. 1760 0
      static/js/Decoder.js
  75. 331 0
      static/js/Player.js
  76. 526 0
      static/js/YUVCanvas.js
  77. 298 0
      static/js/aa.js
  78. 4557 0
      static/js/aac.js
  79. 4022 0
      static/js/aurora.js
  80. 95 0
      static/js/auroraplayer.js
  81. BIN
      static/js/avc.wasm
  82. 270 0
      static/js/carousel.js
  83. 48 0
      static/js/classlist.js
  84. 309 0
      static/js/draw.js
  85. 298 0
      static/js/draw1.js
  86. 1 0
      static/js/jquery-1.10.2.js
  87. 4 0
      static/js/jquery-1.11.0.min.js
  88. 6 0
      static/js/jquery.min.js
  89. 366 0
      static/js/players.js
  90. 4663 0
      static/js/szxcode.js
  91. 100 0
      static/js/web.js
  92. 68 0
      static/js/webapk.js
  93. 218 0
      static/src/controller/buffer-controller.js
  94. 138 0
      static/src/controller/flow-controller.js
  95. 294 0
      static/src/demux/exp-golomb.js
  96. 277 0
      static/src/demux/h264-demuxer.js
  97. 57 0
      static/src/errors.js
  98. 70 0
      static/src/event-handler.js
  99. 40 0
      static/src/events.js
  100. 0 0
      static/src/helper/aac.js

+ 184 - 0
application.properties

@@ -0,0 +1,184 @@
+mysql.addr=192.168.31.159
+#绑定IP
+server.address=0.0.0.0
+# 应用程序端口
+server.port=8020
+server.tomcat.max-threads=1000
+server.tomcat.max-connections=20000
+server.tomcat.min-spare-threads=50
+server.tomcat.accept-count=20000
+# 数据库连接地址
+spring.datasource.url=jdbc:mysql://${mysql.addr}:3306/cloud?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
+# 数据库驱动
+spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
+#spring.datasource.driverClassName = com.mysql.jdbc.Driver
+
+# 数据库用户名
+spring.datasource.username=cloud
+# 数据库密码
+spring.datasource.password=Cloud.123456
+# 参数别名设置
+mybatis.type-aliases-package=com.vcloud.game.vo
+#下划线与驼峰转换
+mybatis.configuration.mapUnderscoreToCamelCase=true
+# 指定连接池中最大的活跃连接数
+spring.datasource.max-active=30
+# 指定连接池最大的空闲连接数量
+spring.datasource.max-idle=30
+# 指定必须保持连接的最小值
+spring.datasource.min-idle=10
+# 指定启动连接池时,初始建立的连接数量
+spring.datasource.initial-size=10
+#指定注册到Eureka Server上的应用名称
+spring.application.name=cloud-game
+spring.rabbitmq.host=192.168.31.159
+spring.rabbitmq.port=5672
+spring.rabbitmq.username=cloud
+spring.rabbitmq.password=Cloud.123456
+#自定义eureka的IP地址,默认是本机
+eureka.addr=127.0.0.1
+#注册中心地址
+eureka.client.serviceUrl.defaultZone=http://${eureka.addr}:8010/eureka/
+#Eureka互相注册要求各个Eureka实例的eureka.instance.hostname
+eureka.instance.hostname=${spring.cloud.client.ip-address}:${server.port}
+# 将自己的IP注册到Eureka Server,并显示IP和端口
+eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
+# 注册到Eureka Server的ip地址
+spring.cloud.inetutils.preferred-networks=127.0.0.1
+eureka.instance.prefer-ip-address=true
+#### ribbon  ####
+# 开启饥饿加载
+ribbon.eager-load.enabled=true
+#### feign  ####
+# 设置属性配置比java代码配置的优先级低
+feign.client.default-to-properties=false
+# 相当于Request.Options
+feign.client.config.default.connect-timeout=10000
+# 相当于Request.Options
+feign.client.config.default.read-timeout=10000
+# 配置Feign的日志级别,相当于代码配置中的Logger
+feign.client.config.default.logger-level=basic
+#feign.client.config.provider-demo01.connect-timeout=5000
+#feign.client.config.provider-demo01.read-timeout=5000
+#feign.client.config.provider-demo01.logger-level=full
+# 延长Hystrix超时时间,默认1000ms
+hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
+# Ribbon超时设置
+#ribbon请求连接的超时时间- 限制3秒内必须请求到服务,并不限制服务处理的返回时间
+ribbon.ConnectTimeout=3000
+#请求处理的超时时间 下级服务响应最大时间,超出时间消费方(路由也是消费方)返回timeout
+ribbon.ReadTimeout=5000
+#当在配置时间窗口内达到此数量的失败后,进行短路。默认20个)
+hystrix.command.default.circuitBreaker.requestVolumeThreshold=20
+#短路多久以后开始尝试是否恢复,默认5s)
+hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=10
+#出错百分比阈值,当达到此阈值后,开始短路。默认50%)
+hystrix.command.default.circuitBreaker.errorThresholdPercentage=50%
+
+##### 重试机制 #######
+#该参数用来开启重试机制,默认是关闭
+#spring.cloud.loadbalancer.retry.enabled=true
+#对所有操作请求都进行重试
+#ribbon.OkToRetryOnAllOperations=true
+#对当前实例的重试次数
+#ribbon.MaxAutoRetries=1
+#切换实例的重试次数
+#ribbon.MaxAutoRetriesNextServer=1
+
+# 定位模板的目录
+spring.mvc.view.prefix=classpath:/templates/
+# 给返回的页面添加后缀名
+spring.mvc.view.suffix=.html
+## 静态资源前缀
+spring.mvc.static-path-pattern=/static/**
+## 默认路径
+spring.resources.static-locations=/META-INF/resources/,classpath:/resources/,classpath:/static/
+
+####### redis #######
+# Redis数据库索引(默认为0)
+spring.redis.database=0
+# Redis服务器地址
+spring.redis.host=192.168.31.159
+# Redis服务器连接端口
+spring.redis.port=6379
+# Redis服务器连接密码(默认为空)
+spring.redis.password=cloud
+# 连接池最大连接数(使用负值表示没有限制)
+spring.redis.jedis.pool.max-active=30
+# 连接池最大阻塞等待时间(使用负值表示没有限制)
+spring.redis.jedis.pool.max-wait=-1
+# 连接池中的最大空闲连接
+spring.redis.jedis.pool.max-idle=30
+# 连接池中的最小空闲连接
+spring.redis.jedis.pool.min-idle=0
+# 连接超时时间(毫秒)
+spring.redis.timeout=5000
+
+###### 日志 #######
+logging.path=/var/log/cloud
+#指向日志配置文件的位置
+logging.config=classpath:logback-spring.xml
+#控制台打印日志格式设置,注意在logback-spring.xml里用CONSOLE_LOG_PATTERN才能获取到
+logging.pattern.console=[%d{yyyy-MM-dd HH:mm:ss}] -- [%-5p]: [%c] -- %m%n
+#文件打印日志格式设置,注意在logback-spring.xml里用FILE_LOG_PATTERN才能获取到
+logging.pattern.file=[%d{yyyy-MM-dd HH:mm:ss}] -- [%-5p]: [%c] -- %m%n
+
+# 字符编码
+spring.http.encoding.charset=UTF-8
+spring.http.encoding.enabled=true
+spring.http.encoding.force=true
+
+# 文件保存路径
+upload.filePath =/usr/vcloud/upload
+
+#springboot 2.0后的配置文件大小方式
+spring.servlet.multipart.max-file-size=2000MB
+spring.servlet.multipart.max-request-size=2000MB
+
+#pagehelper分页插件配置
+pagehelper.helperDialect=mysql
+pagehelper.reasonable=true
+pagehelper.supportMethodsArguments=true
+pagehelper.params=count=countSql
+
+# ftp相关配置
+ftpHost=192.168.31.164
+ftpPort=21
+ftpUserName=ftpadmin
+ftpPassword=admin@123
+basePath=/var/ftp/pub
+
+
+# fadf文件系统配置信息
+# socket连接超时时长
+fdfs.so-timeout=15000
+# 连接tracker服务器超时时长
+fdfs.connect-timeout=8000
+#缩略图生成参数,可选
+fdfs.thumb-image.width=150
+fdfs.thumb-image.height=150
+#TrackerList参数,支持多个
+fdfs.tracker-list=192.168.129.194:22122,192.168.129.196:22122
+fdfs.web-server-url=192.168.129.194:88,192.168.129.196:88
+## 连接池最大数量,配置为-1表示不限制
+fdfs.pool.max-total=-1
+## 每个tracker(key)最大连接数
+fdfs.pool.max-total-per-key=200
+# 每个key对应的连接池最大空闲连接数
+fdfs.pool.max-idle-per-key=100
+# 每个key对应的连接池最小空闲连接数
+fdfs.pool.max_idle_per_key=5
+# 连接耗尽时是否阻塞(默认true)
+fdfs.pool.block-when-exhausted=true
+# 连接耗尽时等待获取连接的最大毫秒数
+fdfs.pool.max-wait-millis=60000
+# 视休眠时间超过了180秒的对象为过期
+fdfs.pool.min-evictable-idle-time-millis=180000
+# 在空闲时检查有效性, 默认false
+fdfs.pool.test-while-idle=true
+# 逐出扫描的时间间隔(毫秒),如果为负数,则不运行逐出线程, 默认-1
+fdfs.pool.time-between-eviction-runs-millis=20000
+# 每次逐出检查时 逐出的最大数目, -1表示清理时检查所有线程
+fdfs.pool.num-tests-per-eviction-run= -1
+# 设置token过期时长为15分钟
+token_timeout = 900000

+ 39 - 0
logback-spring.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>  
+<configuration scan="true" scanPeriod="60 seconds">
+
+    <property name="logging.maxHistory" value="7"/>
+	<!-- spring boot使用日志需要引入这个 -->
+    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+
+    <!-- INFO -->
+    <appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 文件路径 ,注意LOG_PATH是默认值,
+        	它的配置对应application.properties里的logging.path值-->
+        <file>${LOG_PATH}/cloud-game.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 文件名称 -->
+            <fileNamePattern>${LOG_PATH}/cloud-game-%d{yyyy-MM-dd}.log
+            </fileNamePattern>
+            <!-- 文件最大保存历史数量 -->
+            <MaxHistory>${logging.maxHistory}</MaxHistory>
+        </rollingPolicy>
+<!--        <encoder>-->
+<!--            <pattern>${FILE_LOG_PATTERN}</pattern>-->
+<!--            <charset>UTF-8</charset>-->
+<!--        </encoder>-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}  %-5level [%thread]  %logger{80} [%line] - %msg%n</pattern>
+            <charset>utf8</charset>
+        </encoder>
+    </appender>
+
+    <root level="INFO">
+        <appender-ref ref="infoAppender"/>
+    </root>
+
+    <logger name="com.vcloud.game" additivity="false">
+        <level value="INFO" />
+        <appender-ref ref="infoAppender" />
+    </logger>
+
+</configuration>  

File diff suppressed because it is too large
+ 1770 - 0
static/Player/Decoder.js


+ 335 - 0
static/Player/Player.js

@@ -0,0 +1,335 @@
+/*
+
+
+usage:
+
+p = new Player({
+  useWorker: <bool>,
+  workerFile: <defaults to "Decoder.js"> // give path to Decoder.js
+  webgl: true | false | "auto" // defaults to "auto"
+});
+
+// canvas property represents the canvas node
+// put it somewhere in the dom
+p.canvas;
+
+p.webgl; // contains the used rendering mode. if you pass auto to webgl you can see what auto detection resulted in
+
+p.decode(<binary>);
+
+
+*/
+
+
+
+// universal module definition
+(function (root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define(["./Decoder", "./YUVCanvas"], factory);
+    } else if (typeof exports === 'object') {
+        // Node. Does not work with strict CommonJS, but
+        // only CommonJS-like environments that support module.exports,
+        // like Node.
+        module.exports = factory(require("./Decoder"), require("./YUVCanvas"));
+    } else {
+        // Browser globals (root is window)
+        root.Player = factory(root.Decoder, root.YUVCanvas);
+    }
+}(this, function (Decoder, WebGLCanvas) {
+  "use strict";
+  
+  
+  var nowValue = Decoder.nowValue;
+  
+  
+  var Player = function(parOptions){
+    var self = this;
+    this._config = parOptions || {};
+    
+    this.render = true;
+    if (this._config.render === false){
+      this.render = false;
+    };
+    
+    this.nowValue = nowValue;
+    
+    this._config.workerFile = this._config.workerFile || "Decoder.js";
+    if (this._config.preserveDrawingBuffer){
+      this._config.contextOptions = this._config.contextOptions || {};
+      this._config.contextOptions.preserveDrawingBuffer = true;
+    };
+    
+    var webgl = "auto";
+    if (this._config.webgl === true){
+      webgl = true;
+    }else if (this._config.webgl === false){
+      webgl = false;
+    };
+    
+    if (webgl == "auto"){
+      webgl = true;
+      try{
+        if (!window.WebGLRenderingContext) {
+          // the browser doesn't even know what WebGL is
+          webgl = false;
+        } else {
+          var canvas = document.createElement('canvas');
+          var ctx = canvas.getContext("webgl");
+          if (!ctx) {
+            // browser supports WebGL but initialization failed.
+            webgl = false;
+          };
+        };
+      }catch(e){
+        webgl = false;
+      };
+    };
+    
+    this.webgl = webgl;
+    
+    // choose functions
+    if (this.webgl){
+      this.createCanvasObj = this.createCanvasWebGL;
+      this.renderFrame = this.renderFrameWebGL;
+    }else{
+      this.createCanvasObj = this.createCanvasRGB;
+      this.renderFrame = this.renderFrameRGB;
+    };
+    
+    
+    var lastWidth;
+    var lastHeight;
+    var onPictureDecoded = function(buffer, width, height, infos) {
+      self.onPictureDecoded(buffer, width, height, infos);
+      
+      var startTime = nowValue();
+      
+      if (!buffer || !self.render) {
+        return;
+      };
+      
+      self.renderFrame({
+        canvasObj: self.canvasObj,
+        data: buffer,
+        width: width,
+        height: height
+      });
+      
+      if (self.onRenderFrameComplete){
+        self.onRenderFrameComplete({
+          data: buffer,
+          width: width,
+          height: height,
+          infos: infos,
+          canvasObj: self.canvasObj
+        });
+      };
+      
+    };
+    
+    // provide size
+    
+    if (!this._config.size){
+      this._config.size = {};
+    };
+    this._config.size.width = this._config.size.width || 200;
+    this._config.size.height = this._config.size.height || 200;
+    
+    if (this._config.useWorker){
+      var worker = new Worker(this._config.workerFile);
+      this.worker = worker;
+      worker.addEventListener('message', function(e) {
+        var data = e.data;
+        if (data.consoleLog){
+          console.log(data.consoleLog);
+          return;
+        };
+        
+        onPictureDecoded.call(self, new Uint8Array(data.buf, 0, data.length), data.width, data.height, data.infos);
+        
+      }, false);
+      
+      worker.postMessage({type: "Broadway.js - Worker init", options: {
+        rgb: !webgl,
+        memsize: this.memsize,
+        reuseMemory: this._config.reuseMemory ? true : false
+      }});
+      
+      if (this._config.transferMemory){
+        this.decode = function(parData, parInfo){
+          // no copy
+          // instead we are transfering the ownership of the buffer
+          // dangerous!!!
+          
+          worker.postMessage({buf: parData.buffer, offset: parData.byteOffset, length: parData.length, info: parInfo}, [parData.buffer]); // Send data to our worker.
+        };
+        
+      }else{
+        this.decode = function(parData, parInfo){
+          // Copy the sample so that we only do a structured clone of the
+          // region of interest
+          var copyU8 = new Uint8Array(parData.length);
+          copyU8.set( parData, 0, parData.length );
+          worker.postMessage({buf: copyU8.buffer, offset: 0, length: parData.length, info: parInfo}, [copyU8.buffer]); // Send data to our worker.
+        };
+        
+      };
+      
+      if (this._config.reuseMemory){
+        this.recycleMemory = function(parArray){
+          //this.beforeRecycle();
+          worker.postMessage({reuse: parArray.buffer}, [parArray.buffer]); // Send data to our worker.
+          //this.afterRecycle();
+        };
+      }
+      
+    }else{
+      
+      this.decoder = new Decoder({
+        rgb: !webgl
+      });
+      this.decoder.onPictureDecoded = onPictureDecoded;
+
+      this.decode = function(parData, parInfo){
+        self.decoder.decode(parData, parInfo);
+      };
+      
+    };
+    
+    
+    
+    if (this.render){
+      this.canvasObj = this.createCanvasObj({
+        contextOptions: this._config.contextOptions
+      });
+      this.canvas = this.canvasObj.canvas;
+    };
+
+    this.domNode = this.canvas;
+    
+    lastWidth = this._config.size.width;
+    lastHeight = this._config.size.height;
+    
+  };
+  
+  Player.prototype = {
+    
+    onPictureDecoded: function(buffer, width, height, infos){},
+    
+    // call when memory of decoded frames is not used anymore
+    recycleMemory: function(buf){
+    },
+    /*beforeRecycle: function(){},
+    afterRecycle: function(){},*/
+    
+    // for both functions options is:
+    //
+    //  width
+    //  height
+    //  enableScreenshot
+    //
+    // returns a object that has a property canvas which is a html5 canvas
+    createCanvasWebGL: function(options){
+      var canvasObj = this._createBasicCanvasObj(options);
+      canvasObj.contextOptions = options.contextOptions;
+      return canvasObj;
+    },
+    
+    createCanvasRGB: function(options){
+      var canvasObj = this._createBasicCanvasObj(options);
+      return canvasObj;
+    },
+    
+    // part that is the same for webGL and RGB
+    _createBasicCanvasObj: function(options){
+      options = options || {};
+      
+      var obj = {};
+      var width = options.width;
+      if (!width){
+        width = this._config.size.width;
+      };
+      var height = options.height;
+      if (!height){
+        height = this._config.size.height;
+      };
+      obj.canvas = document.createElement('canvas');
+      obj.canvas.width = width;
+      obj.canvas.height = height;
+      obj.canvas.style.backgroundColor = "#0D0E1B";
+      
+      
+      return obj;
+    },
+    
+    // options:
+    //
+    // canvas
+    // data
+    renderFrameWebGL: function(options){
+      
+      var canvasObj = options.canvasObj;
+      
+      var width = options.width || canvasObj.canvas.width;
+      var height = options.height || canvasObj.canvas.height;
+      
+      if (canvasObj.canvas.width !== width || canvasObj.canvas.height !== height || !canvasObj.webGLCanvas){
+        canvasObj.canvas.width = width;
+        canvasObj.canvas.height = height;
+        canvasObj.webGLCanvas = new WebGLCanvas({
+          canvas: canvasObj.canvas,
+          contextOptions: canvasObj.contextOptions,
+          width: width,
+          height: height
+        });
+      };
+      
+      var ylen = width * height;
+      var uvlen = (width / 2) * (height / 2);
+      
+      canvasObj.webGLCanvas.drawNextOutputPicture({
+        yData: options.data.subarray(0, ylen),
+        uData: options.data.subarray(ylen, ylen + uvlen),
+        vData: options.data.subarray(ylen + uvlen, ylen + uvlen + uvlen)
+      });
+      
+      var self = this;
+      self.recycleMemory(options.data);
+      
+    },
+    renderFrameRGB: function(options){
+      var canvasObj = options.canvasObj;
+
+      var width = options.width || canvasObj.canvas.width;
+      var height = options.height || canvasObj.canvas.height;
+      
+      if (canvasObj.canvas.width !== width || canvasObj.canvas.height !== height){
+        canvasObj.canvas.width = width;
+        canvasObj.canvas.height = height;
+      };
+      
+      var ctx = canvasObj.ctx;
+      var imgData = canvasObj.imgData;
+
+      if (!ctx){
+        canvasObj.ctx = canvasObj.canvas.getContext('2d');
+        ctx = canvasObj.ctx;
+
+        canvasObj.imgData = ctx.createImageData(width, height);
+        imgData = canvasObj.imgData;
+      };
+
+      imgData.data.set(options.data);
+      ctx.putImageData(imgData, 0, 0);
+      var self = this;
+      self.recycleMemory(options.data);
+      
+    }
+    
+  };
+  
+  return Player;
+  
+}));
+

+ 551 - 0
static/Player/YUVCanvas.js

@@ -0,0 +1,551 @@
+//
+//  Copyright (c) 2015 Paperspace Co. All rights reserved.
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to
+//  deal in the Software without restriction, including without limitation the
+//  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+//  sell copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+//  IN THE SOFTWARE.
+//
+
+
+// universal module definition
+(function (root, factory) {
+    if (typeof define === 'function' && define.amd) {
+        // AMD. Register as an anonymous module.
+        define([], factory);
+    } else if (typeof exports === 'object') {
+        // Node. Does not work with strict CommonJS, but
+        // only CommonJS-like environments that support module.exports,
+        // like Node.
+        module.exports = factory();
+    } else {
+        // Browser globals (root is window)
+        root.YUVCanvas = factory();
+    }
+}(this, function () {
+
+
+/**
+ * This class can be used to render output pictures from an H264bsdDecoder to a canvas element.
+ * If available the content is rendered using WebGL.
+ */
+  function YUVCanvas(parOptions) {
+    
+    parOptions = parOptions || {};
+    
+    this.canvasElement = parOptions.canvas || document.createElement("canvas");
+    this.contextOptions = parOptions.contextOptions;
+    
+    this.type = parOptions.type || "yuv420";
+    
+    this.customYUV444 = parOptions.customYUV444;
+    
+    this.conversionType = parOptions.conversionType || "rec601";
+
+    this.width = parOptions.width || 640;
+    this.height = parOptions.height || 320;
+    
+    this.animationTime = parOptions.animationTime || 0;
+    
+    this.canvasElement.width = this.width;
+    this.canvasElement.height = this.height;
+
+    this.initContextGL();
+
+    if(this.contextGL) {
+      this.initProgram();
+      this.initBuffers();
+      this.initTextures();
+    };
+    
+
+/**
+ * Draw the next output picture using WebGL
+ */
+    if (this.type === "yuv420"){
+      this.drawNextOuptutPictureGL = function(par) {
+        var gl = this.contextGL;
+        var texturePosBuffer = this.texturePosBuffer;
+        var uTexturePosBuffer = this.uTexturePosBuffer;
+        var vTexturePosBuffer = this.vTexturePosBuffer;
+        
+        var yTextureRef = this.yTextureRef;
+        var uTextureRef = this.uTextureRef;
+        var vTextureRef = this.vTextureRef;
+        
+        var yData = par.yData;
+        var uData = par.uData;
+        var vData = par.vData;
+        
+        var width = this.width;
+        var height = this.height;
+        
+        var yDataPerRow = par.yDataPerRow || width;
+        var yRowCnt     = par.yRowCnt || height;
+        
+        var uDataPerRow = par.uDataPerRow || (width / 2);
+        var uRowCnt     = par.uRowCnt || (height / 2);
+        
+        var vDataPerRow = par.vDataPerRow || uDataPerRow;
+        var vRowCnt     = par.vRowCnt || uRowCnt;
+        
+        gl.viewport(0, 0, width, height);
+
+        var tTop = 0;
+        var tLeft = 0;
+        var tBottom = height / yRowCnt;
+        var tRight = width / yDataPerRow;
+        var texturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, texturePosValues, gl.DYNAMIC_DRAW);
+        
+        if (this.customYUV444){
+          tBottom = height / uRowCnt;
+          tRight = width / uDataPerRow;
+        }else{
+          tBottom = (height / 2) / uRowCnt;
+          tRight = (width / 2) / uDataPerRow;
+        };
+        var uTexturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, uTexturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, uTexturePosValues, gl.DYNAMIC_DRAW);
+        
+        
+        if (this.customYUV444){
+          tBottom = height / vRowCnt;
+          tRight = width / vDataPerRow;
+        }else{
+          tBottom = (height / 2) / vRowCnt;
+          tRight = (width / 2) / vDataPerRow;
+        };
+        var vTexturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, vTexturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, vTexturePosValues, gl.DYNAMIC_DRAW);
+        
+
+        gl.activeTexture(gl.TEXTURE0);
+        gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, yDataPerRow, yRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
+
+        gl.activeTexture(gl.TEXTURE1);
+        gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, uDataPerRow, uRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, uData);
+
+        gl.activeTexture(gl.TEXTURE2);
+        gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, vDataPerRow, vRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, vData);
+
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
+      };
+      
+    }else if (this.type === "yuv422"){
+      this.drawNextOuptutPictureGL = function(par) {
+        var gl = this.contextGL;
+        var texturePosBuffer = this.texturePosBuffer;
+        
+        var textureRef = this.textureRef;
+        
+        var data = par.data;
+        
+        var width = this.width;
+        var height = this.height;
+        
+        var dataPerRow = par.dataPerRow || (width * 2);
+        var rowCnt     = par.rowCnt || height;
+
+        gl.viewport(0, 0, width, height);
+
+        var tTop = 0;
+        var tLeft = 0;
+        var tBottom = height / rowCnt;
+        var tRight = width / (dataPerRow / 2);
+        var texturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, texturePosValues, gl.DYNAMIC_DRAW);
+        
+        gl.uniform2f(gl.getUniformLocation(this.shaderProgram, 'resolution'), dataPerRow, height);
+        
+        gl.activeTexture(gl.TEXTURE0);
+        gl.bindTexture(gl.TEXTURE_2D, textureRef);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, dataPerRow, rowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data);
+
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
+      };
+    };
+    
+  };
+
+  /**
+ * Returns true if the canvas supports WebGL
+ */
+  YUVCanvas.prototype.isWebGL = function() {
+    return this.contextGL;
+  };
+
+  /**
+ * Create the GL context from the canvas element
+ */
+  YUVCanvas.prototype.initContextGL = function() {
+    var canvas = this.canvasElement;
+    var gl = null;
+
+    var validContextNames = ["webgl", "experimental-webgl", "moz-webgl", "webkit-3d"];
+    var nameIndex = 0;
+
+    while(!gl && nameIndex < validContextNames.length) {
+      var contextName = validContextNames[nameIndex];
+
+      try {
+        if (this.contextOptions){
+          gl = canvas.getContext(contextName, this.contextOptions);
+        }else{
+          gl = canvas.getContext(contextName);
+        };
+      } catch (e) {
+        gl = null;
+      }
+
+      if(!gl || typeof gl.getParameter !== "function") {
+        gl = null;
+      }    
+
+      ++nameIndex;
+    };
+
+    this.contextGL = gl;
+  };
+
+/**
+ * Initialize GL shader program
+ */
+YUVCanvas.prototype.initProgram = function() {
+    var gl = this.contextGL;
+
+  // vertex shader is the same for all types
+  var vertexShaderScript;
+  var fragmentShaderScript;
+  
+  if (this.type === "yuv420"){
+
+    vertexShaderScript = [
+      'attribute vec4 vertexPos;',
+      'attribute vec4 texturePos;',
+      'attribute vec4 uTexturePos;',
+      'attribute vec4 vTexturePos;',
+      'varying vec2 textureCoord;',
+      'varying vec2 uTextureCoord;',
+      'varying vec2 vTextureCoord;',
+
+      'void main()',
+      '{',
+      '  gl_Position = vertexPos;',
+      '  textureCoord = texturePos.xy;',
+      '  uTextureCoord = uTexturePos.xy;',
+      '  vTextureCoord = vTexturePos.xy;',
+      '}'
+    ].join('\n');
+    
+    fragmentShaderScript = [
+      'precision highp float;',
+      'varying highp vec2 textureCoord;',
+      'varying highp vec2 uTextureCoord;',
+      'varying highp vec2 vTextureCoord;',
+      'uniform sampler2D ySampler;',
+      'uniform sampler2D uSampler;',
+      'uniform sampler2D vSampler;',
+      'uniform mat4 YUV2RGB;',
+
+      'void main(void) {',
+      '  highp float y = texture2D(ySampler,  textureCoord).r;',
+      '  highp float u = texture2D(uSampler,  uTextureCoord).r;',
+      '  highp float v = texture2D(vSampler,  vTextureCoord).r;',
+      '  gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
+      '}'
+    ].join('\n');
+    
+  }else if (this.type === "yuv422"){
+    vertexShaderScript = [
+      'attribute vec4 vertexPos;',
+      'attribute vec4 texturePos;',
+      'varying vec2 textureCoord;',
+
+      'void main()',
+      '{',
+      '  gl_Position = vertexPos;',
+      '  textureCoord = texturePos.xy;',
+      '}'
+    ].join('\n');
+    
+    fragmentShaderScript = [
+      'precision highp float;',
+      'varying highp vec2 textureCoord;',
+      'uniform sampler2D sampler;',
+      'uniform highp vec2 resolution;',
+      'uniform mat4 YUV2RGB;',
+
+      'void main(void) {',
+      
+      '  highp float texPixX = 1.0 / resolution.x;',
+      '  highp float logPixX = 2.0 / resolution.x;', // half the resolution of the texture
+      '  highp float logHalfPixX = 4.0 / resolution.x;', // half of the logical resolution so every 4th pixel
+      '  highp float steps = floor(textureCoord.x / logPixX);',
+      '  highp float uvSteps = floor(textureCoord.x / logHalfPixX);',
+      '  highp float y = texture2D(sampler, vec2((logPixX * steps) + texPixX, textureCoord.y)).r;',
+      '  highp float u = texture2D(sampler, vec2((logHalfPixX * uvSteps), textureCoord.y)).r;',
+      '  highp float v = texture2D(sampler, vec2((logHalfPixX * uvSteps) + texPixX + texPixX, textureCoord.y)).r;',
+      
+      //'  highp float y = texture2D(sampler,  textureCoord).r;',
+      //'  gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
+      '  gl_FragColor = vec4(y, u, v, 1.0) * YUV2RGB;',
+      '}'
+    ].join('\n');
+  };
+
+  var YUV2RGB = [];
+
+  if (this.conversionType == "rec709") {
+      // ITU-T Rec. 709
+      YUV2RGB = [
+          1.16438,  0.00000,  1.79274, -0.97295,
+          1.16438, -0.21325, -0.53291,  0.30148,
+          1.16438,  2.11240,  0.00000, -1.13340,
+          0, 0, 0, 1,
+      ];
+  } else {
+      // assume ITU-T Rec. 601
+      YUV2RGB = [
+          1.16438,  0.00000,  1.59603, -0.87079,
+          1.16438, -0.39176, -0.81297,  0.52959,
+          1.16438,  2.01723,  0.00000, -1.08139,
+          0, 0, 0, 1
+      ];
+  };
+
+  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
+  gl.shaderSource(vertexShader, vertexShaderScript);
+  gl.compileShader(vertexShader);
+  if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
+    console.log('Vertex shader failed to compile: ' + gl.getShaderInfoLog(vertexShader));
+  }
+
+  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+  gl.shaderSource(fragmentShader, fragmentShaderScript);
+  gl.compileShader(fragmentShader);
+  if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
+    console.log('Fragment shader failed to compile: ' + gl.getShaderInfoLog(fragmentShader));
+  }
+
+  var program = gl.createProgram();
+  gl.attachShader(program, vertexShader);
+  gl.attachShader(program, fragmentShader);
+  gl.linkProgram(program);
+  if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+    console.log('Program failed to compile: ' + gl.getProgramInfoLog(program));
+  }
+
+  gl.useProgram(program);
+
+  var YUV2RGBRef = gl.getUniformLocation(program, 'YUV2RGB');
+  gl.uniformMatrix4fv(YUV2RGBRef, false, YUV2RGB);
+
+  this.shaderProgram = program;
+};
+
+/**
+ * Initialize vertex buffers and attach to shader program
+ */
+YUVCanvas.prototype.initBuffers = function() {
+  var gl = this.contextGL;
+  var program = this.shaderProgram;
+
+  var vertexPosBuffer = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW);
+
+  var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
+  gl.enableVertexAttribArray(vertexPosRef);
+  gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
+  
+  if (this.animationTime){
+    
+    var animationTime = this.animationTime;
+    var timePassed = 0;
+    var stepTime = 15;
+  
+    var aniFun = function(){
+      
+      timePassed += stepTime;
+      var mul = ( 1 * timePassed ) / animationTime;
+      
+      if (timePassed >= animationTime){
+        mul = 1;
+      }else{
+        setTimeout(aniFun, stepTime);
+      };
+      
+      var neg = -1 * mul;
+      var pos = 1 * mul;
+
+      var vertexPosBuffer = gl.createBuffer();
+      gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
+      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([pos, pos, neg, pos, pos, neg, neg, neg]), gl.STATIC_DRAW);
+
+      var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
+      gl.enableVertexAttribArray(vertexPosRef);
+      gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
+      
+      try{
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+      }catch(e){};
+
+    };
+    aniFun();
+    
+  };
+
+  
+
+  var texturePosBuffer = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
+
+  var texturePosRef = gl.getAttribLocation(program, 'texturePos');
+  gl.enableVertexAttribArray(texturePosRef);
+  gl.vertexAttribPointer(texturePosRef, 2, gl.FLOAT, false, 0, 0);
+
+  this.texturePosBuffer = texturePosBuffer;
+
+  if (this.type === "yuv420"){
+    var uTexturePosBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, uTexturePosBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
+
+    var uTexturePosRef = gl.getAttribLocation(program, 'uTexturePos');
+    gl.enableVertexAttribArray(uTexturePosRef);
+    gl.vertexAttribPointer(uTexturePosRef, 2, gl.FLOAT, false, 0, 0);
+
+    this.uTexturePosBuffer = uTexturePosBuffer;
+    
+    
+    var vTexturePosBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vTexturePosBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
+
+    var vTexturePosRef = gl.getAttribLocation(program, 'vTexturePos');
+    gl.enableVertexAttribArray(vTexturePosRef);
+    gl.vertexAttribPointer(vTexturePosRef, 2, gl.FLOAT, false, 0, 0);
+
+    this.vTexturePosBuffer = vTexturePosBuffer;
+  };
+
+};
+
+/**
+ * Initialize GL textures and attach to shader program
+ */
+YUVCanvas.prototype.initTextures = function() {
+  var gl = this.contextGL;
+  var program = this.shaderProgram;
+
+  if (this.type === "yuv420"){
+
+    var yTextureRef = this.initTexture();
+    var ySamplerRef = gl.getUniformLocation(program, 'ySampler');
+    gl.uniform1i(ySamplerRef, 0);
+    this.yTextureRef = yTextureRef;
+
+    var uTextureRef = this.initTexture();
+    var uSamplerRef = gl.getUniformLocation(program, 'uSampler');
+    gl.uniform1i(uSamplerRef, 1);
+    this.uTextureRef = uTextureRef;
+
+    var vTextureRef = this.initTexture();
+    var vSamplerRef = gl.getUniformLocation(program, 'vSampler');
+    gl.uniform1i(vSamplerRef, 2);
+    this.vTextureRef = vTextureRef;
+    
+  }else if (this.type === "yuv422"){
+    // only one texture for 422
+    var textureRef = this.initTexture();
+    var samplerRef = gl.getUniformLocation(program, 'sampler');
+    gl.uniform1i(samplerRef, 0);
+    this.textureRef = textureRef;
+
+  };
+};
+
+/**
+ * Create and configure a single texture
+ */
+YUVCanvas.prototype.initTexture = function() {
+    var gl = this.contextGL;
+
+    var textureRef = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, textureRef);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+    gl.bindTexture(gl.TEXTURE_2D, null);
+
+    return textureRef;
+};
+
+/**
+ * Draw picture data to the canvas.
+ * If this object is using WebGL, the data must be an I420 formatted ArrayBuffer,
+ * Otherwise, data must be an RGBA formatted ArrayBuffer.
+ */
+YUVCanvas.prototype.drawNextOutputPicture = function(width, height, croppingParams, data) {
+    var gl = this.contextGL;
+
+    if(gl) {
+        this.drawNextOuptutPictureGL(width, height, croppingParams, data);
+    } else {
+        this.drawNextOuptutPictureRGBA(width, height, croppingParams, data);
+    }
+};
+
+
+
+/**
+ * Draw next output picture using ARGB data on a 2d canvas.
+ */
+YUVCanvas.prototype.drawNextOuptutPictureRGBA = function(width, height, croppingParams, data) {
+    var canvas = this.canvasElement;
+
+    var croppingParams = null;
+
+    var argbData = data;
+
+    var ctx = canvas.getContext('2d');
+    var imageData = ctx.getImageData(0, 0, width, height);
+    imageData.data.set(argbData);
+
+    if(croppingParams === null) {
+        ctx.putImageData(imageData, 0, 0);
+    } else {
+        ctx.putImageData(imageData, -croppingParams.left, -croppingParams.top, 0, 0, croppingParams.width, croppingParams.height);
+    }
+};
+  
+  return YUVCanvas;
+  
+}));

BIN
static/Player/avc.wasm


BIN
static/avc.wasm


+ 202 - 0
static/css/home.css

@@ -0,0 +1,202 @@
+/* pages/home/home.wxss */
+*{
+	margin: 0;
+	padding: 0;
+}
+
+.heads{
+  padding: 40px 30px 0px 30px;
+  overflow: hidden;
+}
+.heads-left{
+  color: #3399FF;
+}
+.heads-right{
+  width: 60px;
+  height: 60px;
+}
+.heads-right image{
+  width: 100%;
+  height: 100%;
+}
+.left{
+  float: left;
+}
+.right{
+  float: right;
+}
+#wine{
+	width: 100%;
+	height: 100%;
+}
+.canvas{
+ width: 80%;
+height: 100%;
+position: absolute;
+left: 10%;
+border-radius: 10px;
+overflow: hidden;
+top: 5%;
+z-index: -1;
+}
+.canvasfalse{
+   width: 80%;
+height: 90%;
+position: fixed;
+left: 10%;
+border-radius: 20px;
+overflow: hidden;
+top: 5%;
+z-index: -1;
+background:rgba(255,255,255,1);
+box-shadow:0px 0px 100px rgba(0,0,0,0.15);
+}
+.canvas image{
+  width: 100%;
+  height: 100%;
+}
+
+.camvas-head{
+  position: absolute;
+  top: 0;
+  height: 57px;
+  width: 95%;
+  background:rgba(0,0,0,0.4);
+  font-size: 14px;
+  padding: 10px 10px 0px 10px;
+  color:rgba(255,255,255,1);
+   
+  
+}
+.canvastime{
+  font-size: 12px;
+  margin-top: 10px;
+
+}
+
+.addto {
+    width: 60px;
+    height: 60px;
+    position: absolute;
+    z-index: 99;
+    top: 181px;
+    right: 3px;
+
+}
+.addto img{
+  width: 100%;
+  height: 100%;
+}
+.help{
+width: 77px;
+    height: 30px;
+    background: rgba(187,187,187,1);
+    border-radius: 30px 0px 0px 30px;
+    font-size: 13px;
+    line-height: 30px;
+    color: rgba(255,255,255,1);
+    position: absolute;
+    right: -4rem;
+    bottom: 181px;
+    text-align: center;    transition: all 0.2s ease-in;
+}
+
+/* 没登录状态 */
+.notLoggedin{
+    width: 87%;
+    height: 36%;
+    margin: 0 auto;
+    margin-top: 38%;
+}
+.notLoggedin img{
+  width: 100%;
+  height: 100%;
+  margin: 0 auto;
+}
+.notLoggedin-text{
+font-size: 16px;
+    color: #FDB456;
+    margin-top: 8px;
+    text-align: center;
+}
+
+.notLoggedin-bt{
+    width: 153px;
+    height: 45px;
+    line-height: 45px;
+    background: linear-gradient(272deg,rgba(255,201,133,1) 0%,rgba(255,177,78,1) 100%);
+    box-shadow: 0px 4px 8px rgba(251,145,11,0.2);
+    opacity: 1;
+    border-radius: 10px;
+    font-size: 16px;
+    color: #D17F00;
+    text-align: center;
+    margin: 0 auto;
+    margin-top: 22px;
+}
+.vip image{
+  width:60px;
+  height: 30px;
+  margin-left: 10px;
+}
+
+.tips{
+  position: fixed;
+  width: 100%;
+  height: 100%;
+  bottom: 0;
+  background: rgba(0,0,0,0.8);
+    z-index:511;
+}
+.tipsMane{
+  width: 70%;
+  height:326px;
+  background: #fff;
+  z-index: 999;
+  position: absolute;
+  top: 30%;
+  left: 15%;
+  border-radius:10px;
+}
+.tipsTitle{
+  padding: 30px 0;
+  text-align: center;
+  font-size:32px;
+}
+.tipsTEXT{
+  font-size: 28px;
+  text-align: center;
+  color: #333333;
+}
+
+.tipsBt{
+  width: 80%;
+  height: 80px;
+  line-height: 80px;
+  background:#0886F5;
+  text-align: center;
+  font-size: 32px;
+  margin: 0 auto;
+  color: #fff;
+  border-radius:10px; 
+  margin-top: 35px;
+}
+
+.tipsimg{
+  width: 68px;
+  height: 68px;
+  background: #fff;
+  position: absolute;
+  z-index: 999;
+  top: 350px;
+  border-radius:50%;
+  left: 44%;
+}
+.tipsimg img{
+   width: 100%;
+   height: 100%;
+}
+.vipimg{
+width: 24px;
+    height: 18px;
+}

+ 331 - 0
static/css/homeNew.css

@@ -0,0 +1,331 @@
+/* pages/home/home.wxss */
+* {
+	margin: 0;
+	padding: 0;
+}
+
+.heads {
+	padding: 40px 30px 0px 30px;
+	overflow: hidden;
+}
+
+.heads-left {
+	color: #3399FF;
+}
+
+.heads-right {
+	width: 60px;
+	height: 60px;
+}
+
+.heads-right image {
+	width: 100%;
+	height: 100%;
+}
+
+.left {
+	float: left;
+}
+
+.right {
+	float: right;
+}
+
+#wine {
+	width: 100%;
+	height: 100%;
+}
+
+.canvas {
+	width: 80%;
+	height: 80%;
+	position: absolute;
+	left: 8%;
+	border-radius: 10px;
+	overflow: hidden;
+	top: 9%;
+	z-index: -1;
+	background: #F6F6F6;
+	box-shadow: 3px 3px 4px 0px rgba(136, 142, 151, 0.18), -3px -3px 4px 0px #FFFFFF;
+	border-radius: 28px;
+	padding: 7px 8px;
+}
+
+.canvasfalse {
+	width: 80%;
+	height: 90%;
+	position: fixed;
+	left: 10%;
+	border-radius: 20px;
+	overflow: hidden;
+	top: 5%;
+	z-index: -1;
+	background: rgba(255, 255, 255, 1);
+	box-shadow: 0px 0px 100px rgba(0, 0, 0, 0.15);
+}
+
+.canvas image {
+	width: 100%;
+	height: 100%;
+}
+
+.camvas-head {
+	position: absolute;
+	top: 0;
+	height: 57px;
+	width: 89%;
+	background: rgba(0, 0, 0, 0.4);
+	font-size: 14px;
+	padding: 0px 10px 0px 10px;
+	color: rgba(255, 255, 255, 1);
+	margin-top: 7px;
+	border-radius: 20px;
+}
+
+.canvastime {
+	font-size: 12px;
+	margin-top: 10px;
+
+}
+
+.addto {
+	width: 60px;
+	height: 60px;
+	position: absolute;
+	z-index: 99;
+	top: 181px;
+	right: 3px;
+
+}
+
+.addto img {
+	width: 100%;
+	height: 100%;
+}
+
+.help {
+	width: 77px;
+	height: 30px;
+	background: rgba(187, 187, 187, 1);
+	border-radius: 30px 0px 0px 30px;
+	font-size: 13px;
+	line-height: 30px;
+	color: rgba(255, 255, 255, 1);
+	position: absolute;
+	right: -4rem;
+	bottom: 181px;
+	text-align: center;
+	transition: all 0.2s ease-in;
+}
+
+/* 没登录状态 */
+.notLoggedin {
+	width: 87%;
+	height: 36%;
+	margin: 0 auto;
+	margin-top: 38%;
+}
+
+.notLoggedin img {
+	width: 100%;
+	height: 100%;
+	margin: 0 auto;
+}
+
+.notLoggedin-text {
+	font-size: 16px;
+	color: #FDB456;
+	margin-top: 8px;
+	text-align: center;
+}
+
+.notLoggedin-bt {
+	width: 153px;
+	height: 45px;
+	line-height: 45px;
+	background: linear-gradient(272deg, rgba(255, 201, 133, 1) 0%, rgba(255, 177, 78, 1) 100%);
+	box-shadow: 0px 4px 8px rgba(251, 145, 11, 0.2);
+	opacity: 1;
+	border-radius: 10px;
+	font-size: 16px;
+	color: #D17F00;
+	text-align: center;
+	margin: 0 auto;
+	margin-top: 22px;
+}
+
+.vip image {
+	width: 60px;
+	height: 30px;
+	margin-left: 10px;
+}
+
+.tips {
+	position: fixed;
+	width: 100%;
+	height: 100%;
+	bottom: 0;
+	background: rgba(0, 0, 0, 0.8);
+	z-index: 511;
+}
+
+.tipsMane {
+	width: 70%;
+	height: 326px;
+	background: #fff;
+	z-index: 999;
+	position: absolute;
+	top: 30%;
+	left: 15%;
+	border-radius: 10px;
+}
+
+.tipsTitle {
+	padding: 30px 0;
+	text-align: center;
+	font-size: 32px;
+}
+
+.tipsTEXT {
+	font-size: 28px;
+	text-align: center;
+	color: #333333;
+}
+
+.tipsBt {
+	width: 80%;
+	height: 80px;
+	line-height: 80px;
+	background: #0886F5;
+	text-align: center;
+	font-size: 32px;
+	margin: 0 auto;
+	color: #fff;
+	border-radius: 10px;
+	margin-top: 35px;
+}
+
+.tipsimg {
+	width: 68px;
+	height: 68px;
+	background: #fff;
+	position: absolute;
+	z-index: 999;
+	top: 350px;
+	border-radius: 50%;
+	left: 44%;
+}
+
+.tipsimg img {
+	width: 100%;
+	height: 100%;
+}
+
+.vipimg {
+	width: 24px;
+	height: 18px;
+}
+
+.newhelp {
+	display: flex;
+
+	font-size: 12px;
+	font-family: PingFangSC-Regular, PingFang SC;
+	font-weight: 400;
+	color: #999999;
+	line-height: 17px;
+	align-items: center;
+	position: absolute;
+	top: 0;
+	left: 0;
+	margin-top: 10px;
+	margin-left: 15px;
+}
+
+.newhelp .font {
+	text-decoration: underline;
+	margin-left: 2px;
+}
+
+.newhelp .helpImg {
+	width: 0.875rem;
+	height: 0.875rem;
+}
+
+.newhelp .helpImg img {
+	width: 100%;
+	height: 100%;
+}
+
+.buyIcon {
+	position: absolute;
+	top: 0;
+	right: 0;
+	/* 	margin-top: 0.625rem;
+	margin-right: 0.625rem;
+	 */
+}
+
+.th_renew {
+	width: 3rem;
+	height: 1.375rem;
+	background: linear-gradient(90deg, #FFC52C 0%, #FF9D3B 100%);
+	box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.1);
+	border-radius: 0.8125rem;
+}
+
+.tophead {
+	display: flex;
+}
+
+.camvas-head {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.thl-font {
+
+	font-size: 0.75rem;
+	font-family: PingFangSC-Semibold, PingFang SC;
+	font-weight: 600;
+	color: #FFFFFF;
+}
+
+.thl-time {
+
+	font-size: 0.625rem;
+	font-family: PingFangSC-Regular, PingFang SC;
+	font-weight: 400;
+	color: #FFFFFF;
+	transform: scale(.8);
+	margin-left: -0.9375rem;
+}
+
+.th_right {
+	margin-left: 0.625rem;
+}
+
+.kongWine {
+	background: #FFFFFF;
+	border-radius: 20px;
+}
+
+.kp_btn {
+	width: 7.5rem;
+	height: 1.875rem;
+	background: linear-gradient(104deg, #5682FF 0%, #285CF1 100%);
+	border-radius: 20px;
+	line-height: 1.875rem;
+
+	font-size: 0.75rem;
+	font-family: MicrosoftYaHei;
+	color: #FFFFFF;
+	line-height: 1.875rem;
+	margin: 0 auto;
+	margin-top: 15px;
+}
+
+.kp_img {
+	padding-top: 50%;
+}

File diff suppressed because it is too large
+ 1216 - 0
static/css/index.css


File diff suppressed because it is too large
+ 13 - 0
static/css/swiper-bundle.min.css


File diff suppressed because it is too large
+ 14 - 0
static/css/swiper-bundle.min.js


+ 400 - 0
static/distss/WXdraw.js

@@ -0,0 +1,400 @@
+//画布
+var canvas;
+var context;
+//蒙版
+var canvas_bak = document.getElementById("box");;
+var context_bak;
+
+var canvasWidth = 720;
+var canvasHeight = 1280;
+
+var canvasTop;
+var canvasLeft;
+var winHeight = window.screen.height - window.innerHeight
+var vowidth = window.screen.width
+var topwinHeightDraw = window.screen.height - window.innerHeight + 30; //计算title top 头部
+var numse = window.screen.height //-winHeight
+
+//计算title top 头部
+if (numse <= 70) {
+
+	var voheight = window.screen.height - winHeight - 34 - 20
+} else {
+	console.log("numse>>>", numse)
+	var voheight = window.screen.height - topwinHeightDraw - 20
+}
+
+//console.log("画笔大小>>>",window.innerHeight)
+//画笔大小
+var size = 1;
+var color = '#000000';
+var resolving
+//alert(winHeight)
+var url = window.location.href;
+url = url.split('/')
+
+var query = window.location.search.substring(1);
+// debugger
+// query = "clientType=3&username=WqXTc1593762177&userCardId=377"
+// debugger
+var vars = query.split("&");
+var data = {}
+var clientType = vars.find(e => {
+	return e.startsWith('clientType')
+}) || ''
+var cardIp = vars.find(e => {
+	return e.startsWith('cardIp')
+}) || ''
+var port = vars.find(e => {
+	return e.startsWith('port')
+}) || ''
+
+var sn = vars.find(e => {
+	return e.startsWith('sn')
+}) || ''
+var username = vars.find(e => {
+	return e.startsWith('username')
+}) || ''
+var userCardId = vars.find(e => {
+	return e.startsWith('userCardId')
+}) || ''
+var ip = vars.find(e => {
+	return e.startsWith('ip')
+}) || ''
+
+var data = {}
+data.clientType = clientType.substring(11, clientType.length)
+
+data.cardIp = cardIp.substring(7, cardIp.length)
+
+data.port = port.substring(5, port.length)
+
+data.sn = sn.substring(3, sn.length)
+data.username = username.substring(9, username.length)
+data.userCardId = userCardId.substring(11, userCardId.length)
+data.ip = ip.substring(3, ip.length)
+// var urlss=url[2]
+// urlss = "14.215.128.96"
+// urlss = '192.168.31.20'
+urlss = 'test.androidscloud.com'
+// debugger
+var cUrl = ''
+if (data.clientType == 3) {
+	cUrl = "wss://" + urlss + "/authControlWebSocket?" + "clientType=" + data.clientType + "&username=" + data.username +
+		"&userCardId=" + data.userCardId
+} else if (data.clientType == 2) {
+	// cUrl = "wss://" + urlss + "/shareWebSocket?" + "clientType=" + data.clientType + "&username=" + data.username +
+	// 	"&userCardId=" + data.userCardId + "&ip=" + data.ip
+	cUrl = "wss://test.androidscloud.com/videoWebSocket?clientType=1&cardIp=14.215.128.96&port=2005&sn=RK3930C2301900005";
+} else {
+	cUrl = "wss://" + urlss + "/controlWebSocket?" + "clientType=" + data.clientType + "&cardIp=" + data.cardIp + "&port=" +
+		data.port + "&sn=" + data.sn
+}
+console.log(cUrl, 'curl')
+// var cUrl = Number(data.clientType) === 3? "ws://"+urlss+"/authControlWebSocket?"+"clientType="+data.clientType+"&username="+data.username+"&userCardId="+data.userCardId : "ws://"+urlss+"/controlWebSocket?"+"clientType="+data.clientType+"&cardIp="+data.cardIp+"&port="+data.port+"&sn="+data.sn
+var wsss = new WebSocket(cUrl);
+console.log('wsssss==============', wsss)
+wsss.binaryType = 'arraybuffer';
+////
+// wsss = new WebSocket(
+// 	"ws://14.215.128.96/authControlWebSocket?clientType=3&username=WqXTc1593762177&userCardId=377");
+
+wsss.onopen = function() {
+	console.log("onopen==============");
+	var pings = {
+		"event": "getScreenStatus"
+	}
+	wsss.send(JSON.stringify(pings));
+	var bitRate = {
+		"data": {
+			"bitRate": 2243000
+		},
+		"event": "bitRate"
+	}
+	wsss.send(JSON.stringify(bitRate));
+};
+wsss.onmessage = function(event) {
+	// console.log("onMessage==============", event);
+	// var resets = JSON.parse(event.data)
+	// var resets = event.data;
+	// resets.errorMsg && alert(resets.errorMsg)
+	// resolving = resets.data.orientation
+	// if (resolving == 1) {} else {}
+	// console.log('>>>resolvingresolvingresolving', resolving)
+
+};
+wsss.onclose = function(event) {
+	console.log("onclose==============");
+};
+wsss.onerror = function(event) {
+	console.log("onerror==============");
+};
+$('#box').on("click", function() {
+
+	draw_graph('pencil', this)
+})
+//剪切板
+$(".upload").on("click", function() {
+	let texts = $(this).attr("data-text")
+	if (texts == "uploads") {
+		$(".mainbox").css({
+			"display": "block"
+		})
+		$(".sbox").css({
+			"display": "none"
+		})
+	} else if (texts == "Signout") {
+		//		alert()
+
+	}
+})
+
+//home 控制home
+$(".botmat1img").on("click", function() {
+	let codes = $(this).attr("data-text")
+	console.log(codes)
+	if (codes == "home") {
+		var bitRate = {
+			"data": {
+				"keyCode": "3"
+			},
+			"event": "keyCode"
+		}
+		wsss.send(JSON.stringify(bitRate));
+	} else if (codes == "return") {
+		var bitRate = {
+			"data": {
+				"keyCode": "4"
+			},
+			"event": "keyCode"
+		}
+		wsss.send(JSON.stringify(bitRate));
+	} else if (codes == "gengduo") {
+		var bitRate = {
+			"data": {
+				"keyCode": "187"
+			},
+			"event": "keyCode"
+		}
+		wsss.send(JSON.stringify(bitRate));
+	}
+
+})
+//高清控制
+$(".PictureQuality").on("click", function() {
+	$(this).addClass("avit").siblings().removeClass('avit')
+	let id = $(this).attr("data-id")
+	var bitRate = {
+		"data": {
+			"bitRate": id
+		},
+		"event": "bitRate"
+	}
+	wsss.send(JSON.stringify(bitRate));
+	console.log(id)
+})
+
+//画图形
+var draw_graph = function(graphType, obj) {
+	console.log('111》》》', graphType)
+	//把蒙版放于画板上面
+	//$("#canvas_bak").css("z-index",1);
+	$("#container").css("z-index", 30);
+	$("#dedit").css("z-index", 20);
+	//先画在蒙版上 再复制到画布上
+
+	chooseImg(obj);
+	var canDraw = false;
+
+	var startX;
+	var startY;
+
+	//鼠标按下获取 开始xy开始画图
+	var touchstart = function(e) {
+		$('.control-right-img').attr({
+			"data-id": "2"
+		})
+		$(".leftmains").css({
+			"right": "-4rem"
+		})
+		//		.toFixed(2)
+		var touchfor = e.originalEvent.targetTouches; //for 的手指数组
+		var touch = e.originalEvent.targetTouches[0];
+		var thochlethng = e.originalEvent.targetTouches.length
+		//是否横屏
+		if (resolving == 0) {
+			let ping
+			for (let i = 0; i < touchfor.length; i++) {
+				let cawidthXs = touchfor[i].pageY * (1280 / voheight)
+				let caheightYs = 720 - touchfor[i].pageX * (720 / vowidth)
+				ping = {
+					"data": {
+						"action": 0,
+						"count": touchfor.length,
+						"pointerId": i,
+						"x": cawidthXs.toFixed(2),
+						"y": caheightYs.toFixed(2)
+					},
+					"event": "0"
+				}
+			}
+			wsss.send(JSON.stringify(ping));
+			console.log("鼠标按下>>>", ping)
+		} else {
+			let ping
+			for (let i = 0; i < touchfor.length; i++) {
+				let cawidthXs = touchfor[i].pageX * (720 / vowidth)
+				let caheightYs = touchfor[i].pageY * (1280 / voheight)
+				ping = {
+					"data": {
+						"action": 0,
+						"count": touchfor.length,
+						"pointerId": i,
+						"x": cawidthXs.toFixed(2),
+						"y": caheightYs.toFixed(2)
+					},
+					"event": "0"
+				}
+
+			}
+			wsss.send(JSON.stringify(ping));
+			console.log("鼠标按下>>>", ping)
+		}
+
+		canDraw = true;
+
+	};
+
+	//鼠标离开 把蒙版canvas的图片生成到canvas中
+	var touchend = function(e) {
+		var touchfor = e.originalEvent.changedTouches; //for 的手指数组
+		var touch = e.originalEvent.changedTouches[0];
+		var thochlethng = e.originalEvent.changedTouches.length
+		//	 alert(thochlethng)
+		//是否横屏 morePortionUp
+		if (resolving == 0) {
+			let ping
+			for (let i = 0; i < touchfor.length; i++) {
+				let cawidthXs = touchfor[i].pageY * (1280 / voheight)
+				let caheightYs = 720 - touchfor[i].pageX * (720 / vowidth)
+				ping = {
+					"data": {
+						"action": 1,
+						"count": touchfor.length,
+						"pointerId": i,
+						"x": cawidthXs.toFixed(2),
+						"y": caheightYs.toFixed(2)
+					},
+					"event": "1"
+				}
+			}
+
+			wsss.send(JSON.stringify(ping));
+
+		} else {
+			let ping
+			for (let i = 0; i < touchfor.length; i++) {
+				let cawidthXs = touchfor[i].pageX * (720 / vowidth)
+				let caheightYs = touchfor[i].pageY * (1280 / voheight)
+				ping = {
+					"data": {
+						"action": 1,
+						"count": touchfor.length,
+						"pointerId": i,
+						"x": cawidthXs.toFixed(2),
+						"y": caheightYs.toFixed(2)
+					},
+					"event": "1"
+				}
+			}
+
+			wsss.send(JSON.stringify(ping));
+		}
+
+		canDraw = false;
+
+	};
+
+	//清空层 云手机超出屏幕的开关
+	var clearContext = function(type) {
+		canDraw = false;
+	}
+
+	// 鼠标移动
+	var touchmove = function(e) {
+
+		e = e || window.event;
+		var touchfor = e.originalEvent.targetTouches; //for 的手指数组
+		var touch = e.originalEvent.targetTouches[0];
+		var thochlethng = e.originalEvent.targetTouches.length
+		let ping
+		//是否横屏  morePortionMove
+		if (resolving == 0) {
+			let obj = []
+			for (let i = 0; i < touchfor.length; i++) {
+				let cawidthXs = touchfor[i].pageY * (1280 / voheight)
+				let caheightYs = 720 - touchfor[i].pageX * (720 / vowidth)
+
+				ping = {
+					"data": {
+						"action": 2,
+						"count": touchfor.length,
+						"pointerId": i,
+						"x": cawidthXs.toFixed(2),
+						"y": caheightYs.toFixed(2)
+					},
+					"event": "2"
+				}
+
+			}
+
+			wsss.send(JSON.stringify(ping));
+		} else {
+			let ping
+			for (let i = 0; i < touchfor.length; i++) {
+				let cawidthXs = touchfor[i].pageX * (720 / vowidth)
+				let caheightYs = touchfor[i].pageY * (1280 / voheight)
+				ping = {
+					"data": {
+						"action": 2,
+						"count": touchfor.length,
+						"pointerId": i,
+						"x": cawidthXs.toFixed(2),
+						"y": caheightYs.toFixed(2)
+					},
+					"event": "2"
+				}
+
+			}
+
+			wsss.send(JSON.stringify(ping));
+		}
+
+
+
+		//				var ping = {"data":{"action":2,"count":1,"pointerId":0,"x":cawidthX.toFixed(2),"y":caheightY.toFixed(2)},"event":"2"}	    
+
+
+
+	};
+
+	//鼠标离开区域以外 除了涂鸦 都清空
+	var mouseout = function() {
+
+		if (graphType != 'handwriting') {
+			clearContext();
+
+		}
+	}
+
+	$(canvas_bak).unbind();
+	$(canvas_bak).bind('touchstart', touchstart);
+	$(canvas_bak).bind('touchmove', touchmove);
+	$(canvas_bak).bind('touchend', touchend);
+	$(canvas_bak).bind('mouseout', mouseout);
+}
+
+//选择功能按钮 修改样式
+function chooseImg(obj) {
+
+}

+ 291 - 0
static/distss/draw.js

@@ -0,0 +1,291 @@
+//画布
+var canvas;
+var context;
+//蒙版
+var canvas_bak = document.getElementById("box");;
+var context_bak;
+
+var canvasWidth = 720;
+var canvasHeight = 1280;
+
+var canvasTop;
+var canvasLeft;
+var winHeight = window.screen.height - window.innerHeight
+var vowidth = window.screen.width
+var topwinHeightDraw = window.screen.height - window.innerHeight + 30; //计算title top 头部
+var numse = window.screen.height //-winHeight
+
+//计算title top 头部
+if (numse <= 70) {
+
+	var voheight = window.screen.height - winHeight - 34
+} else {
+	console.log("numse>>>", numse)
+	var voheight = window.screen.height - topwinHeightDraw
+}
+
+//console.log("画笔大小>>>",window.innerHeight)
+//画笔大小
+var size = 1;
+var color = '#000000';
+var resolving
+//alert(winHeight)
+                       var url = window.location.href;
+                       url = url.split('/')
+
+            var query = window.location.search.substring(1);
+          var vars = query.split("&");
+          var data = {}
+var clientType = vars.find(e => {
+             return e.startsWith('clientType')
+         })
+var cardIp = vars.find(e => {
+             return e.startsWith('cardIp')
+         })
+var port = vars.find(e => {
+             return e.startsWith('port')
+         })
+
+var sn = vars.find(e => {
+             return e.startsWith('sn')
+         })
+ var data = {}         
+           data.clientType=clientType.substring(11, clientType.length)
+
+           data.cardIp=cardIp.substring(7, cardIp.length)
+
+           data.port=port.substring(5, port.length)
+
+           data.sn=sn.substring(3, sn.length)
+           var urlss= url[2]
+var wsss = new WebSocket("ws://"+urlss+"/controlWebSocket?"+"clientType="+data.clientType+"&cardIp="+data.cardIp+"&port="+data.port+"&sn="+data.sn);
+
+////
+// var wsss = new WebSocket(
+// 	"ws://14.215.128.96/controlWebSocket?clientType=0&cardIp=30.30.30.58&port=9100&sn=RK3930C2301900060");
+
+wsss.onopen = function() {
+	var pings = {
+		"event": "getScreenStatus"
+	}
+	wsss.send(JSON.stringify(pings));
+   var bitRate ={"data":{"bitRate":400},"event":"bitRate"}
+     wsss.send(JSON.stringify(bitRate));
+};
+wsss.onmessage = function(event) {
+	var resets = JSON.parse(event.data)
+
+	resolving = resets.data.orientation
+	if (resolving == 1) {} else {}
+
+};
+wsss.onclose = function(event) {
+
+};
+wsss.onerror = function(event) {
+
+};
+$('#box').on("click", function() {
+
+	draw_graph('pencil', this)
+})
+//剪切板
+$(".upload").on("click",function(){
+	let texts = $(this).attr("data-text")
+	if(texts == "uploads"){
+		$(".mainbox").css({"display":"block"})
+		$(".sbox").css({"display":"none"})
+	}
+})
+
+//home 控制home
+$(".botmat1img").on("click",function(){
+	let codes= $(this).attr("data-text")
+	console.log(codes)
+	if(codes == "home"){
+		var bitRate ={"data":{"keyCode":"3"},"event":"keyCode"} 
+     wsss.send(JSON.stringify(bitRate));
+	}else if(codes == "return"){
+		var bitRate ={"data":{"keyCode":"4"},"event":"keyCode"} 
+     wsss.send(JSON.stringify(bitRate));
+	}else if(codes == "gengduo"){
+		var bitRate ={"data":{"keyCode":"187"},"event":"keyCode"} 
+     wsss.send(JSON.stringify(bitRate));
+	}
+	
+})
+//高清控制
+$(".PictureQuality").on("click",function(){
+	 $(this).addClass("avit").siblings().removeClass('avit')
+	 let id= $(this).attr("data-id")
+	 var bitRate ={"data":{"bitRate":id},"event":"bitRate"}
+     wsss.send(JSON.stringify(bitRate));
+	 console.log(id)
+})
+
+//画图形
+var draw_graph = function(graphType, obj) {
+	console.log('111》》》', graphType)
+	//把蒙版放于画板上面
+	//$("#canvas_bak").css("z-index",1);
+	$("#container").css("z-index", 30);
+	$("#dedit").css("z-index", 20);
+	//先画在蒙版上 再复制到画布上
+
+	chooseImg(obj);
+	var canDraw = false;
+
+	var startX;
+	var startY;
+    var touchNum = 0
+	var touchPos = {};
+	//鼠标按下获取 开始xy开始画图
+	var touchstart = function(e) {
+		//		.toFixed(2)
+		var touchfor = e.originalEvent.targetTouches; //for 的手指数组
+		var touch = e.originalEvent.targetTouches[0];
+		var thochlethng = e.originalEvent.targetTouches.length
+		touchNum = thochlethng;
+		touchPos = touch;
+		e.preventDefault()
+		 
+		if(touchfor.length == 1){
+			var pingssfe = {
+		      "event": "getScreenStatus"
+	        }
+			wsss.send(JSON.stringify(pingssfe));
+		}
+			
+	
+		
+		//是否横屏
+		if (resolving == 0) {
+			let ping
+			for (let i = 0; i < touchfor.length; i++) {
+				let cawidthXs = touchfor[i].pageY * (1280 / voheight)
+				let caheightYs = 720 - touchfor[i].pageX * (720 / vowidth)
+			    ping =  {"data":{"action":0,"count":touchfor.length,"pointerId":i,"x":cawidthXs.toFixed(2),"y":caheightYs.toFixed(2)},"event":"0"}
+			    wsss.send(JSON.stringify(ping));
+			}
+			
+		} else {
+			let ping
+			for (let i = 0; i < touchfor.length; i++) {
+				let cawidthXs = touchfor[i].pageX * (720 / vowidth)
+				let caheightYs = touchfor[i].pageY * (1280 / voheight)
+             ping =  {"data":{"action":0,"count":touchfor.length,"pointerId":i,"x":cawidthXs.toFixed(2),"y":caheightYs.toFixed(2)},"event":"0"}
+				wsss.send(JSON.stringify(ping));
+			}
+			
+			
+		}
+
+	canDraw = true;
+
+	};
+
+	//鼠标离开 把蒙版canvas的图片生成到canvas中
+	var touchend = function(e) {
+		e.preventDefault()
+        var touchfor = e.originalEvent.changedTouches; //for 的手指数组
+		var touch = e.originalEvent.changedTouches[0];
+		var thochlethng = e.originalEvent.changedTouches.length
+		//	 alert(thochlethng)
+		//是否横屏 morePortionUp
+        if (resolving == 0) {
+        	let ping
+        	for (let i = 0; i < touchfor.length; i++) {
+        		let cawidthXs = touchfor[i].pageY * (1280 / voheight)
+        		let caheightYs = 720 - touchfor[i].pageX * (720 / vowidth)
+        		ping = {"data":{"action":1,"count":touchfor.length,"pointerId":i,"x":cawidthXs.toFixed(2),"y":caheightYs.toFixed(2)},"event":"1"}
+        	
+        	}
+        	(touchNum <= 1 || (touch.pageY == touchPos.pageY && touch.pageX == touchPos.pageX)) && wsss.send(JSON.stringify(ping));
+        	
+        	
+        
+        } else {
+        	let ping
+        	for (let i = 0; i < touchfor.length; i++) {
+        		let cawidthXs = touchfor[i].pageX * (720 / vowidth)
+        		let caheightYs = touchfor[i].pageY * (1280 / voheight)
+        	    ping = {"data":{"action":1,"count":touchfor.length,"pointerId":i,"x":cawidthXs.toFixed(2),"y":caheightYs.toFixed(2)},"event":"1"}
+        	
+        	}
+        	(touchNum <= 1 || (touch.pageY == touchPos.pageY && touch.pageX == touchPos.pageX)) && wsss.send(JSON.stringify(ping));
+        	
+        	
+        }
+
+		canDraw = false;
+
+	};
+
+	//清空层 云手机超出屏幕的开关
+	var clearContext = function(type) {
+		canDraw = false;
+	}
+
+	// 鼠标移动
+	var touchmove = function(e) {
+
+		e = e || window.event;
+		var touchfor = e.originalEvent.targetTouches; //for 的手指数组
+		var touch = e.originalEvent.targetTouches[0];
+		var thochlethng = e.originalEvent.targetTouches.length
+		touchNum = thochlethng;
+		touchPos = touch;
+		e.preventDefault();
+		let ping
+		//是否横屏  morePortionMove
+		if (resolving == 0) {
+			 let obj = []
+			 for (let i = 0; i < touchfor.length; i++) {
+			 	let cawidthXs = touchfor[i].pageY * (1280 / voheight)
+			 	let caheightYs = 720 - touchfor[i].pageX * (720 / vowidth)
+	
+				ping = {"data":{"action":2,"count":touchfor.length,"pointerId":i,"x":cawidthXs.toFixed(2),"y":caheightYs.toFixed(2)},"event":"2"}
+			 wsss.send(JSON.stringify(ping));
+			 }
+		
+		   
+		} else {
+			 let ping
+			 for (let i = 0; i < touchfor.length; i++) {
+			 	let cawidthXs = touchfor[i].pageX * (720 / vowidth)
+			 	let caheightYs = touchfor[i].pageY * (1280 / voheight)
+			 	ping = {"data":{"action":2,"count":touchfor.length,"pointerId":i,"x":cawidthXs.toFixed(2),"y":caheightYs.toFixed(2)},"event":"2"}
+			 wsss.send(JSON.stringify(ping));
+			 }
+			
+			
+		}
+
+
+
+		//				var ping = {"data":{"action":2,"count":1,"pointerId":0,"x":cawidthX.toFixed(2),"y":caheightY.toFixed(2)},"event":"2"}	    
+	
+
+
+	};
+
+	//鼠标离开区域以外 除了涂鸦 都清空
+	var mouseout = function() {
+
+		if (graphType != 'handwriting') {
+			clearContext();
+
+		}
+	}
+
+	$(canvas_bak).unbind();
+	$(canvas_bak).bind('touchstart', touchstart);
+	$(canvas_bak).bind('touchmove', touchmove);
+	$(canvas_bak).bind('touchend', touchend);
+	$(canvas_bak).bind('mouseout', mouseout);
+}
+
+//选择功能按钮 修改样式
+function chooseImg(obj) {
+
+}

BIN
static/fonts/Gloss_And_Bloom.ttf


BIN
static/fonts/hei.ttf


BIN
static/img/anniu_icon.png


BIN
static/img/bangzu_icon.png


BIN
static/img/beijing_pic.png


BIN
static/img/expenienceCenter/anniu_icon.png


BIN
static/img/expenienceCenter/beijing_pic.png


BIN
static/img/expenienceCenter/beijing_pic2.png


BIN
static/img/expenienceCenter/bg.png


BIN
static/img/expenienceCenter/bg2.png


BIN
static/img/expenienceCenter/bg3.png


BIN
static/img/expenienceCenter/biankuang_shuoming_pic.png


BIN
static/img/expenienceCenter/biankuang_tiyanzhongxin_pic.png


BIN
static/img/expenienceCenter/biankuang_tubiao_pic.png


BIN
static/img/expenienceCenter/biaotikuang2_pic.png


BIN
static/img/expenienceCenter/biaotikuang_pic.png


BIN
static/img/expenienceCenter/you2_icon.png


BIN
static/img/expenienceCenter/you_icon.png


BIN
static/img/expenienceCenter/youimg.png


BIN
static/img/expenienceCenter/zuo2_icon.png


BIN
static/img/expenienceCenter/zuo_icon.png


BIN
static/img/goumai_icon.png


BIN
static/img/goumai_icon@2x.png


BIN
static/img/goumai_pic.png


BIN
static/img/home_icon.png


BIN
static/img/musicfalse.png


BIN
static/img/musicturn.png


BIN
static/img/shang_icon.png


BIN
static/img/svip_icon.png


BIN
static/img/tianjia_icon.png


BIN
static/img/tianjiashouji_pic.png


BIN
static/img/time.png


BIN
static/img/u760.jpg


BIN
static/img/vip_icon.png


BIN
static/img/wx/fanhui_icon.png


BIN
static/img/wx/gengduo_icon.png


BIN
static/img/wx/guanbi_icon.png


BIN
static/img/wx/home_icon.png


BIN
static/img/wx/jianqieban_icon.png


BIN
static/img/wx/shangchuan_icon.png


BIN
static/img/wx/tianjiashouji_pic.png


BIN
static/img/wx/tuichu_icon.png


BIN
static/img/xia_icon.png


BIN
static/img/xingdong_icon.png


BIN
static/img/xingyao_icon.png


BIN
static/img/xuanfu_icon.png


+ 183 - 0
static/js/AAC — Audiocogs.html

@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<!-- saved from url=(0032)http://audiocogs.org/codecs/aac/ -->
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+		<title>AAC — Audiocogs</title>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+
+		<link rel="stylesheet" type="text/css" href="./AAC — Audiocogs_files/all.min.css">
+		<link rel="shortcut icon" href="http://audiocogs.org/favicon.ico">
+		<!--[if lt IE 9]>
+	<script src="/scripts/html5shiv.js"></script>
+	<![endif]-->
+
+		<link rel="alternate" type="application/rss+xml" title="Audiocogs Blog" href="http://audiocogs.org/rss.xml">
+	</head>
+	<body class="codec">
+		<section>
+			<header class="main">
+				<div class="inner">
+					<h1>
+						<div id="name">
+							<a href="http://audiocogs.org/">Audiocogs</a>
+						</div>
+						<div id="social">
+							<a href="http://twitter.com/audiocogs"><img id="twitterbird" class="twitter" width="30" height="30" src="./AAC — Audiocogs_files/white-twitter.png"
+								 alt="Audiocogs on twitter."></a>
+							<a href="https://github.com/audiocogs"><img id="white-octocat" class="github" width="30" height="30" src="./AAC — Audiocogs_files/white-octocat.png"
+								 alt="Audiocogs on github."></a>
+						</div>
+					</h1>
+				</div>
+			</header>
+			<section id="content">
+				<div class="title-nav">
+					<ul>
+
+						<li><a href="http://audiocogs.org/codecs">Codecs</a></li>
+
+						<li><a href="http://audiocogs.org/codecs/mp3">MP3</a></li>
+						<li><a href="http://audiocogs.org/codecs/alac">ALAC</a></li>
+						<li><a href="http://audiocogs.org/codecs/flac">FLAC</a></li>
+						<li><a href="http://audiocogs.org/codecs/aac">AAC</a></li>
+
+					</ul>
+				</div>
+
+				<article>
+					<header>
+
+						<h1 id="article_title">AAC</h1>
+
+
+					</header>
+
+
+					<link rel="stylesheet" href="./AAC — Audiocogs_files/player.css">
+
+					<script src="./AAC — Audiocogs_files/classlist.js"></script>
+					<script>
+						var unsupported;
+						if (!window.Audio || !('mozWriteAudio' in new Audio()) && !window.AudioContext && !window.webkitAudioContext) {
+							unsupported = true;
+							document.body.classList.add("unsupported");
+						}
+					</script>
+					<div id="unsupported">
+						We're really sorry about this, but it looks like your browser doesn't support an Audio API. Please
+						try these demos in Chrome 15+ or Firefox 8+ or watch a <a href="http://vimeo.com/33919455">screencast</a>.
+					</div>
+
+
+					<p>Advanced Audio Coding (AAC) is a standardized, high quality lossy audio codec, designed as the successor to the
+						MP3 format. AAC is now one of the most widely deployed audio codecs, and such names as the iTunes Store
+						distribute music in the AAC format.</p>
+
+					<p>AAC can be played in a limited number of browsers using the HTML5 audio element, however, some browsers do not
+						support the codec for various reasons. <a href="https://github.com/ofmlabs/aac.js">AAC.js</a> is a JavaScript AAC
+						decoder that enables decoding and playback of AAC files in all browsers supported by the <a href="https://github.com/ofmlabs/aurora.js">Aurora.js</a>
+						audio framework.</p>
+
+
+					<!-- <script src="./AAC — Audiocogs_files/player.js"></script>
+					<script src="./AAC — Audiocogs_files/auroraplayer.js"></script> -->
+					<script src="players.js"></script>
+                    <script src="auroraplayer.js"></script>
+					<div class="player" id="dgplayer" tabindex="0">
+						<div class="avatar">
+							<img src="./AAC — Audiocogs_files/fallback_album_art.png">
+						</div>
+
+						<span class="title">undefined</span>
+						<span class="artist">undefined</span>
+
+						<div class="button"></div>
+
+						<div class="volume">
+							<img src="./AAC — Audiocogs_files/volume_high.png">
+							<div class="track">
+								<div class="progress" style="height: 60px;"></div>
+								<div class="handle" style="transform: translate3d(0px, -52px, 0px);"></div>
+							</div>
+							<img src="./AAC — Audiocogs_files/volume_low.png">
+						</div>
+
+						<div class="seek">
+							<span>0:12</span>
+							<div class="track">
+								<div class="loaded" style="width: 228px;"></div>
+								<div class="progress" style="width: 220.115px;"></div>
+							</div>
+							<span>-0:00</span>
+						</div>
+
+						<div class="file_button"></div>
+						<span class="file_description">Choose an AAC file on your computer</span>
+					</div>
+
+					<!-- <script src="./AAC — Audiocogs_files/aurora.js"></script>
+					<script src="./AAC — Audiocogs_files/aac.js"></script> -->
+                    <script src="aurora.js"></script>
+                    <script src="aac.js"></script>
+					<script type="text/javascript">
+						// Chrome doesn't support changing the sample rate, and uses whatever the hardware supports.
+						// We cheat here.  Instead of resampling on the fly, we're currently just loading two different
+						// files based on common hardware sample rates.
+						
+						//Chrome不支持改变采样率,而是使用硬件支持的任何东西。
+						
+						//我们在这里作弊。只是重新取样,而不是现在的两个
+						
+						//基于通用硬件采样率的文件。
+						 
+						var _sampleRate = (function() {
+							var AudioContext = (window.AudioContext || window.webkitAudioContext);
+							if (!AudioContext)
+								return 44100;
+
+							return new AudioContext().sampleRate;
+						}());
+
+						(function(DGPlayer) {
+							if (unsupported) return;
+
+							DGPlayer.volume = 100;
+
+							var player, onplay;
+							var url = '';
+
+							DGPlayer.on('play', onplay = function() {
+								console.log("走到播放里面了play");
+								if (player)
+									player.disconnect();
+
+								player = new DGAuroraPlayer(AV.Player.fromURL(url), DGPlayer);
+								DGPlayer.off('play', onplay);
+							});
+
+							DGPlayer.on('file', function(file) {
+								console.log("走到播放里面了file");
+								if (file) {
+									if (player)
+										player.disconnect();
+
+									player = new DGAuroraPlayer(AV.Player.fromFile(file), DGPlayer);
+									DGPlayer.off('play', onplay);
+								}
+							});
+
+						}(DGPlayer(document.getElementById('dgplayer'))));
+					</script>
+
+
+				</article>
+
+			</section>
+		</section>
+
+
+
+	</body>
+</html>

File diff suppressed because it is too large
+ 4655 - 0
static/js/AAC — Audiocogs_files/aac.js


File diff suppressed because it is too large
+ 3 - 0
static/js/AAC — Audiocogs_files/all.min.css


File diff suppressed because it is too large
+ 4003 - 0
static/js/AAC — Audiocogs_files/aurora.js


+ 83 - 0
static/js/AAC — Audiocogs_files/auroraplayer.js

@@ -0,0 +1,83 @@
+UNKNOWN_ART = '/dgplayer/resources/fallback_album_art.png';
+
+function DGAuroraPlayer(player, DGPlayer) {
+    this.player = player;
+    this.ui = DGPlayer;
+    
+    DGPlayer.seekTime = 0;
+    DGPlayer.duration = 0;
+    DGPlayer.bufferProgress = 0;
+
+    var onplay, onpause, onvolume, onformat, onbuffer, onprogress, onduration, onmetadata;
+    
+    DGPlayer.on('play', onplay = function() {
+        player.play();
+        DGPlayer.state = 'playing';
+    });
+    
+    DGPlayer.on('pause', onpause = function() {
+        player.pause();
+        DGPlayer.state = 'paused';
+    });
+    
+    DGPlayer.on('volume', onvolume = function(value) {
+        player.volume = value;
+    });
+    
+    player.on('buffer', onbuffer = function(percent) {
+        DGPlayer.bufferProgress = percent;
+    });
+    
+    player.on('progress', onprogress = function(time) {
+        DGPlayer.seekTime = time;
+    });
+    
+    player.on('duration', onduration = function(duration) {
+        DGPlayer.duration = duration;
+    });
+    
+    player.on('metadata', onmetadata = function(data) {
+        DGPlayer.songTitle = data.title;
+        DGPlayer.songArtist = data.artist;
+        
+        if (data.coverArt) {
+            DGPlayer.coverArt = data.coverArt.toBlobURL();
+        } else {
+            DGPlayer.coverArt = UNKNOWN_ART;
+        }
+    });
+    
+    var originalDescription = DGPlayer.fileDescription;
+    player.on('error', onerror = function(e) {
+        // reset state
+        DGPlayer.state = 'paused';
+        DGPlayer.duration = 0;
+        DGPlayer.bufferProgress = 0;
+        DGPlayer.seekTime = 0;
+        DGPlayer.coverArt = UNKNOWN_ART;
+        DGPlayer.songTitle = 'Unknown Title';
+        DGPlayer.songArtist = 'Unknown Artist';
+        
+        DGPlayer.fileDescription = "Hmm. I don't recognize that format. Try another.";
+        setTimeout(function() {
+            DGPlayer.fileDescription = originalDescription;
+        }, 3000);
+    });
+    
+    player.volume = DGPlayer.volume;
+    player.play();
+    DGPlayer.state = 'playing';
+    
+    this.disconnect = function() {
+        if (player) player.stop();
+        
+        DGPlayer.off('play', onplay);
+        DGPlayer.off('pause', onpause);
+        DGPlayer.off('volume', onvolume);
+        player.off('buffer', onbuffer);
+        player.off('format', onformat);
+        player.off('progress', onprogress);
+        player.off('duration', onduration);
+        player.off('metadata', onmetadata);
+    }
+}

+ 53 - 0
static/js/AAC — Audiocogs_files/classlist.js

@@ -0,0 +1,53 @@
+/*
+ * Minimal classList shim for IE 9
+ * By Devon Govett
+ * MIT LICENSE
+ */
+
+
+if (!("classList" in document.documentElement) && Object.defineProperty && typeof HTMLElement !== 'undefined') {
+    Object.defineProperty(HTMLElement.prototype, 'classList', {
+        get: function() {
+            var self = this;
+            function update(fn) {
+                return function(value) {
+                    var classes = self.className.split(/\s+/),
+                        index = classes.indexOf(value);
+
+                    fn(classes, index, value);
+                    self.className = classes.join(" ");
+                }
+            }
+
+            var ret = {                    
+                add: update(function(classes, index, value) {
+                    ~index || classes.push(value);
+                }),
+
+                remove: update(function(classes, index) {
+                    ~index && classes.splice(index, 1);
+                }),
+
+                toggle: update(function(classes, index, value) {
+                    ~index ? classes.splice(index, 1) : classes.push(value);
+                }),
+
+                contains: function(value) {
+                    return !!~self.className.split(/\s+/).indexOf(value);
+                },
+
+                item: function(i) {
+                    return self.className.split(/\s+/)[i] || null;
+                }
+            };
+            
+            Object.defineProperty(ret, 'length', {
+                get: function() {
+                    return self.className.split(/\s+/).length;
+                }
+            });
+
+            return ret;
+        }
+    });
+}

BIN
static/js/AAC — Audiocogs_files/fallback_album_art.png


+ 283 - 0
static/js/AAC — Audiocogs_files/player.css

@@ -0,0 +1,283 @@
+@font-face {
+    font-family: 'Digital7Mono';
+    src: url('resources/digital-7_mono.eot');
+    src: url('resources/digital-7_mono.woff') format('woff'),
+         url('resources/digital-7_mono.eot?#iefix') format('embedded-opentype'),
+         url('resources/digital-7_mono.ttf') format('truetype');
+    font-weight: normal;
+    font-style: normal;
+}
+
+#unsupported {
+    display: none;
+    font-family: Helvetica, Arial, sans-serif;
+    top: 0;
+    margin: 10px;
+    padding: 10px;
+    color: white;
+    text-shadow: black 0 1px 3px;
+    background: #c50202;
+    background: -webkit-linear-gradient(#c50202, #950202);
+    background: -moz-linear-gradient(#c50202, #950202);
+    background: -o-linear-gradient(#c50202, #950202);
+    box-shadow: black 0 1px 10px;
+    -webkit-box-shadow: black 0 1px 10px;
+    -moz-box-shadow: black 0 1px 10px;
+    border-radius: 5px;
+}
+#unsupported a {
+	color: white;
+}
+.unsupported #unsupported {
+    display: block;
+}
+
+.player {
+    margin-top: 20px;
+    padding: 18px;
+    width: 323px;
+    height: 212px;
+    background: #202329;
+    background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZCIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzMyMzYzQyIgLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMxNzE5MUUiIC8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgc3R5bGU9ImZpbGw6dXJsKCNncmFkKTsiIC8+PC9zdmc+);
+    background: -webkit-linear-gradient(#32363C, #17191e);
+    background: -moz-linear-gradient(#32363C, #17191e);
+    background: -o-linear-gradient(#32363C, #17191e);
+    border-radius: 5px;
+    border: 1px solid rgba(0, 0, 0, 0.85);
+    box-shadow: rgba(255, 255, 255, 0.15) 0 1px 0 inset, black 0 2px 18px;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    cursor: default;
+    position: relative;
+    outline: none;
+}
+
+.player, .player * {
+    -webkit-box-sizing: content-box;
+    -moz-box-sizing: content-box;
+    -ms-box-sizing: content-box;
+    -o-box-sizing: content-box;
+    box-sizing: content-box;
+}
+
+.player::selection {
+    background:transparent
+}
+        
+.player .avatar {
+    position: relative;
+    width: 130px;
+    height: 130px;
+    border: 1px solid rgba(0, 0, 0, 0.63);
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    box-shadow: rgba(0, 0, 0, 0.35) 0 1px 5px;
+    float: left;
+    margin: 0 10px 30px 0;
+}
+
+.player .avatar img {
+    width: 100%;
+    height: 100%;
+}
+
+.player .avatar::after {
+    position: absolute;
+    top: 0; left: 0; right: 0; bottom: -1px;
+    content: " ";
+    background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSI1MCUiIHN0b3AtY29sb3I9InJnYmEoMjU1LCAyNTUsIDI1NSwgMC4xNSkiIC8+PHN0b3Agb2Zmc2V0PSI1MCUiIHN0b3AtY29sb3I9InJnYmEoMjU1LCAyNTUsIDI1NSwgMCkiIC8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgc3R5bGU9ImZpbGw6dXJsKCNncmFkKTsiIC8+PC9zdmc+);
+    background: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 50%, transparent 50%);
+    background: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 50%, transparent 50%);
+    background: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 50%, transparent 50%);
+    box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0 inset;
+}
+
+.player span.title {
+    font-family: Helvetica, Arial, "DejaVu Sans", sans-serif;
+    font-weight: 500;
+    font-size: 13px;
+    color: white;
+    margin: 0;
+    text-shadow: black 0 -1px 0;
+    display: block;
+    height: 15px;
+    line-height: 13px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.player > span.artist {
+    font-family: Helvetica, Arial, "DejaVu Sans Condensed", sans-serif;
+    font-size: 11px;
+    color: #A7AAB1;
+    text-shadow: black 0 -1px 0;
+    display: block;
+    line-height: 13px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.player a {
+    color: #A7AAB1;
+    text-decoration: none;
+}
+
+.player .button {
+    background: url(resources/playbutton.png);
+    width: 95px;
+    height: 95px;
+    float: left;
+    margin-left: 30px;
+    margin-top: 6px;
+    -webkit-tap-highlight-color: transparent;
+}
+
+.player .button:active {
+    background: url(resources/playbutton_active.png);
+}
+
+.player .button.pause {
+    background: url(resources/pausebutton.png);
+}
+
+.player .button.pause:active {
+    background: url(resources/pausebutton_active.png);
+}
+
+.player .volume {
+    position: absolute;
+    right: 15px;
+    top: 49px;
+}
+
+.player .volume img {
+    display: block;
+}
+
+.player .volume .track {
+    width: 8px;
+    height: 65px;
+    display: inline-block;
+    vertical-align: top;
+    margin: 5px 0 7px 2px;
+    background: #1B1D23;
+    box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, black 0 1px 4px inset;
+    border-radius: 5px;
+    position: relative;
+}
+
+.player .volume .track .progress {
+    width: 6px;
+    height: 0;
+    background: #0D0E10;
+    position: absolute;
+    bottom: 1px;
+    left: 1px;
+    box-shadow: black 0 1px 4px inset;
+    border-radius: 3px;
+}
+
+.player .volume .track .handle {
+    width: 20px;
+    height: 20px;
+    background: url(resources/handle.png);
+    position: absolute;
+    left: -6px;
+    bottom: 0;
+}
+
+.player .volume .track .handle.animatable {
+    -webkit-transition: -webkit-transform 200ms;
+    -moz-transition: bottom 200ms;
+    -o-transition: bottom 200ms;
+}
+
+.player .volume img {
+    -webkit-user-drag: none;
+}
+
+.player .volume .track .handle.active:before {
+    position: absolute;
+    content: " ";
+    top: 3px; left: 3px;
+    width: 12px; height: 12px;
+    border-radius: 13px;
+    box-shadow: white 0 0 12px;
+}
+
+.player .seek {
+    position: absolute;
+    left: 20px;
+    top: 167px;
+}
+
+.player .seek span {
+    color: white;
+    font-family: Helvetica, Arial, "DejaVu Sans Condensed", sans-serif;
+    font-size: 12px;
+    text-shadow: black 0 -1px 0;
+}
+
+.player .seek .track {
+    width: 230px;
+    height: 10px;
+    display: inline-block;
+    vertical-align: top;
+    margin: 8px 15px 0 15px;
+    background: #151619;
+    box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0, black 0 1px 4px inset;
+    border-radius: 5px;
+    position: relative;
+}
+
+.player .seek .track .progress {
+    width: 0;
+    height: 8px;
+    border-radius: 4px;
+    position: absolute;
+    top: 1px; left: 1px;
+    background: #73B3C5;
+    background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZCIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI0E5RDVERSIgLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM2OUFEQkUiIC8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgc3R5bGU9ImZpbGw6dXJsKCNncmFkKTsiIC8+PC9zdmc+);
+    background: -webkit-linear-gradient(#A9D5DE, #69ADBE);
+    background: -moz-linear-gradient(#A9D5DE, #69ADBE);
+    background: -o-linear-gradient(#A9D5DE, #69ADBE);
+}
+
+.player .seek .track .loaded {
+    width: 0;
+    height: 8px;
+    border-radius: 4px;
+    position: absolute;
+    top: 1px; left: 1px;
+    background: -webkit-linear-gradient(#202328, #191B1E);
+    background: -moz-linear-gradient(#202328, #191B1E);
+    background: -o-linear-gradient(#202328, #191B1E);
+}
+
+.player .file_button {
+    position: absolute;
+    bottom: 2px;
+    left: 6px;
+    width: 52px;
+    height: 52px;
+    -webkit-tap-highlight-color: transparent;
+    background: url(resources/choosefile.png);
+}
+
+.player .file_button:active {
+    background: url(resources/choosefile_pressed.png);
+}
+
+.player span.file_description {
+    font-family: Helvetica, Arial, "DejaVu Sans Condensed", sans-serif;
+    font-weight: 100;
+    font-size: 12px;
+    color: #A7AAB1;
+    text-shadow: black 0 -1px 0;
+    display: block;
+    position: absolute;
+    left: 60px;
+    bottom: 16px;
+}

+ 363 - 0
static/js/AAC — Audiocogs_files/player.js

@@ -0,0 +1,363 @@
+function DGPlayer(root) {
+    
+    // Get elements
+    var events = {},
+        state = 'paused';
+    
+    // Preload images
+    new Image().src = "/dgplayer/resources/playbutton_active.png";
+    new Image().src = "/dgplayer/resources/pausebutton.png";
+    new Image().src = "/dgplayer/resources/pausebutton_active.png";
+    new Image().src = "/dgplayer/resources/choosefile_pressed.png";
+    
+    // Prevent text selection in IE
+    root.onselectstart = function() {
+        return false
+    }
+    
+    var seekBar = (function() {
+        
+        var loading = root.querySelector(".seek .track .loaded"),
+            progress = root.querySelector(".seek .track .progress"),
+            played = root.querySelector(".seek span:first-child"),
+            remaining = root.querySelector(".seek span:last-child"),
+            maxWidth = loading.parentNode.offsetWidth - 2,
+            loaded = 0, currentTime = 0, trackLength = 0, oldSeconds = 0;
+            
+            
+        function pad(input) {
+            return ("00" + input).slice(-2);
+        }
+        
+        return {
+            getTrackLength: function() {
+                return trackLength;
+            },
+
+            setTrackLength: function(time) {
+                trackLength = time;
+                this.seekTime = currentTime;
+            },
+
+            getCurrentTime: function() {
+                return currentTime;
+            },
+
+            setCurrentTime: function(time) {
+                oldSeconds = Math.floor(currentTime / 1000 % 60);;
+                currentTime = time;
+                
+                if (currentTime >= trackLength && trackLength > 0)
+                    emit("pause");
+
+                var t = currentTime / 1000,
+                    seconds = Math.floor(t % 60),
+                    minutes = Math.floor((t /= 60) % 60);
+                    
+                if (seconds === oldSeconds)
+                    return;
+                
+                played.innerHTML = minutes + ':' + pad(seconds);
+                
+                // only show the progress bar and remaining time if we know the duration
+                if (trackLength > 0) {
+                    var r = (trackLength - currentTime) / 1000,
+                        remainingSeconds = Math.floor(r % 60),
+                        remainingMinutes = Math.floor((r /= 60) % 60);
+                    
+                    remaining.innerHTML = '-' + remainingMinutes + ':' + pad(remainingSeconds);
+                    position = Math.max(0, Math.min(1, currentTime / trackLength));
+                    progress.style.width = maxWidth * position + 'px';
+                } else {
+                    remaining.innerHTML = '-0:00';
+                }
+            },
+            
+            getAmountLoaded: function() {
+                return loaded;
+            },
+            
+            setAmountLoaded: function(val) {
+                loaded = Math.max(0, Math.min(100, val));
+                loading.style.width = maxWidth * (loaded / 100) + 'px';
+            }
+        }
+        
+    })();
+        
+    var playpause = (function() {
+        
+        var button = root.querySelector(".button"),
+            interval = null, playing = false;
+            
+        button.onclick = function() {
+            emit(playing ? "pause" : "play");
+        };
+
+        root.addEventListener('keyup', function(e) {
+            e.which === 32 && emit(playing ? "pause" : "play");
+        });
+        
+        function setPlaying(play) {
+            if (playing = play)
+                button.classList.add("pause");
+            else
+                button.classList.remove("pause");
+        }
+        
+        return {
+            setPlaying: setPlaying,
+            getPlaying: function() {
+                return playing;
+            }
+        }
+        
+    })();
+    
+    var slider = (function() {
+        
+        var handle = root.querySelector(".volume .handle"),
+            progress = root.querySelector(".volume .progress"),
+            track = root.querySelector(".volume .track")
+            volumeLeft = root.querySelector(".volume img:first-child"),
+            volumeRight = root.querySelector(".volume img:last-child");
+            
+        var lastY = 0, 
+            down = false,
+            height = 65,
+            handleSize = 20,
+            min = -8,
+            max = height - handleSize / 2 - 3,
+            curY = Math.floor(height / 2 - handleSize / 2),
+            value = 50;
+            
+        function update(dontEmit) {
+            if ('webkitTransform' in handle.style)
+                handle.style.webkitTransform = "translate3d(0, " + (-max - min + curY) + "px" + ", 0)";
+            else
+                handle.style.bottom = max + min - curY + "px";
+
+            progress.style.height = max - curY + "px";
+            value = Math.round(100 - (curY - min) / (max - min) * 100);
+            
+            if (!dontEmit)
+                emit("volume", value);
+        }
+        update();
+        
+        handle.onmousedown = handle.ontouchstart = function(e) {
+            lastY = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
+            down = true;
+            e.stopPropagation();
+            handle.classList.add("active");
+            e.preventDefault();
+        }
+        
+        function onMove(e) {
+            var eventY = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
+            var y = Math.max(min, Math.min(max, curY + eventY - lastY));
+            if (!down || y === curY) return;
+
+            curY = y;
+            lastY = eventY;
+            update();
+        }
+        
+        function onUp(e) {
+            if(!down) return;
+            down = false;
+            handle.classList.remove("active");
+        }
+        
+        document.addEventListener("mousemove", onMove, false);
+        document.addEventListener("touchmove", onMove, false);
+        document.addEventListener("mouseup", onUp, false);
+        document.addEventListener("touchend", onUp, false);
+        
+        // Handle clicking on the minimum and maximum volume icons
+        function animate() {
+            handle.classList.add("animatable");
+            progress.classList.add("animatable");
+
+            update();
+
+            setTimeout(function() {
+                handle.classList.remove("animatable");
+                progress.classList.remove("animatable");
+            }, 250);
+        }
+        
+        volumeLeft.onclick = function() {
+            curY = min;
+            animate();
+        }
+
+        volumeRight.onclick = function() {
+            curY = max;
+            animate();
+        }
+        
+        // Handle clicking on the track
+        track.onmousedown = track.ontouchstart = function(e) {
+            var y = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
+            
+            // Get the absolute offsetTop of the track
+            var offset = 0, obj = track;
+            while (obj) {
+                offset += obj.offsetTop - obj.scrollTop;
+                obj = obj.offsetParent;
+            }
+            
+            curY = Math.max(min, Math.min(max, y - offset - (handleSize + min)));
+            handle.onmousedown(e);
+            update();
+        }
+        
+        return {
+            getValue: function() {
+                return value;
+            },
+            
+            setValue: function(val) {
+                val = Math.max(0, Math.min(100, val));
+                curY = max - (val / 100) * (max - min);
+                update(true);
+            }
+        }
+        
+    })();
+    
+    var filebutton = (function() {
+        
+        var button = root.querySelector('.file_button'),
+            input = document.createElement('input');
+            
+        input.setAttribute('type', 'file');
+        input.style.opacity = 0;
+        input.style.position = 'absolute';
+        input.style.left = '-1000px';
+        
+        input.onchange = function(e) {
+            emit('file', input.files[0]);
+        }
+        
+        button.onclick = function() {
+            input.click();
+			 console.log("bbbbbbbbbbbbb");
+        }
+        
+    })();
+    
+    function emit(event) {
+        if (!events[event]) return;
+        
+        var args = Array.prototype.slice.call(arguments, 1),
+            callbacks = events[event];
+            
+        for (var i = 0, len = callbacks.length; i < len; i++) {
+            callbacks[i].apply(null, args);
+        }
+    } 
+    
+    var API = {
+        on: function(event, fn) {
+            events[event] || (events[event] = []);
+            events[event].push(fn);
+        },
+        
+        off: function(event, fn) {
+            var eventsOf = events[event],
+                index = eventsOf.indexOf(fn);
+                
+            ~index && eventsOf.splice(index, 1);
+        }
+    };
+    
+    // Object.defineProperty shim for Opera
+    Object.defineProperty || (Object.defineProperty = function(obj, prop, config) {
+        if (config.get && obj.__defineGetter__)
+            obj.__defineGetter__(prop, config.get);
+            
+        if (config.set && obj.__defineSetter__)
+            obj.__defineSetter__(prop, config.set);
+    })
+    
+    Object.defineProperty(API, "bufferProgress", {
+        get: seekBar.getAmountLoaded,
+        set: seekBar.setAmountLoaded
+    });
+    
+    Object.defineProperty(API, "state", {
+        set: function(newstate) {
+            playpause.setPlaying(newstate == 'playing' || newstate == 'buffering');                
+            state = newstate;
+        },
+        
+        get: function() { 
+            return state;
+        }
+    });
+    
+    Object.defineProperty(API, "duration", {
+        get: seekBar.getTrackLength,
+        set: seekBar.setTrackLength
+    });
+    
+    Object.defineProperty(API, "seekTime", {
+        get: seekBar.getCurrentTime,
+        set: seekBar.setCurrentTime
+    });
+    
+    Object.defineProperty(API, "volume", {
+        get: slider.getValue,
+        set: slider.setValue
+    });
+    
+    var img = root.querySelector(".avatar img");
+    Object.defineProperty(API, "coverArt", {
+        get: function() {
+            return img.src;
+        },
+        
+        set: function(src) {
+            img.src = src;
+        }
+    });
+    
+    var title = root.querySelector("span.title"),
+        artist = root.querySelector("span.artist");
+        
+    Object.defineProperty(API, "songTitle", {
+        get: function() {
+            return title.innerHTML;
+        },
+        
+        set: function(val) {
+            title.innerHTML = val;
+        }
+    });
+    
+    Object.defineProperty(API, "songArtist", {
+        get: function() {
+            return artist.innerHTML;
+        },
+        
+        set: function(val) {
+            artist.innerHTML = val;
+        }
+    });
+    
+    var description = root.querySelector('.file_description');
+    Object.defineProperty(API, "fileDescription", {
+        get: function() {
+            return description.innerHTML;
+        },
+        
+        set: function(val) {
+            description.innerHTML = val;
+        }
+    });
+    
+    return API;
+    
+}

BIN
static/js/AAC — Audiocogs_files/volume_high.png


BIN
static/js/AAC — Audiocogs_files/volume_low.png


BIN
static/js/AAC — Audiocogs_files/white-octocat.png


BIN
static/js/AAC — Audiocogs_files/white-twitter.png


File diff suppressed because it is too large
+ 1760 - 0
static/js/Decoder.js


+ 331 - 0
static/js/Player.js

@@ -0,0 +1,331 @@
+/*
+
+
+usage:
+
+p = new Player({
+  useWorker: <bool>,
+  workerFile: <defaults to "Decoder.js"> // give path to Decoder.js
+  webgl: true | false | "auto" // defaults to "auto"
+});
+
+// canvas property represents the canvas node
+// put it somewhere in the dom
+p.canvas;
+
+p.webgl; // contains the used rendering mode. if you pass auto to webgl you can see what auto detection resulted in
+
+p.decode(<binary>);
+
+
+*/
+
+
+
+// 通用模块定义
+(function (root, factory) {
+    if (typeof define === 'function' && define.amd) {
+     
+        define(["./Decoder", "./YUVCanvas"], factory);
+    } else if (typeof exports === 'object') {
+       
+        module.exports = factory(require("./Decoder"), require("./YUVCanvas"));
+    } else {
+        // 浏览器全局(根是窗口)
+        root.Player = factory(root.Decoder, root.YUVCanvas);
+    }
+}(this, function (Decoder, WebGLCanvas) {
+  "use strict";
+  
+  
+  var nowValue = Decoder.nowValue;
+  
+  
+  var Player = function(parOptions){
+  	console.log(1111111)
+    var self = this;
+    this._config = parOptions || {};
+    
+    this.render = true;
+    if (this._config.render === false){
+      this.render = false;
+    };
+    
+    this.nowValue = nowValue;
+    
+    this._config.workerFile = this._config.workerFile || "Decoder.js";
+    if (this._config.preserveDrawingBuffer){
+      this._config.contextOptions = this._config.contextOptions || {};
+      this._config.contextOptions.preserveDrawingBuffer = true;
+    };
+    
+    var webgl = "auto";
+    if (this._config.webgl === true){
+      webgl = true;
+    }else if (this._config.webgl === false){
+      webgl = false;
+    };
+    
+    if (webgl == "auto"){
+      webgl = true;
+      try{
+        if (!window.WebGLRenderingContext) {
+          // 浏览器甚至不知道WebGLjs
+          webgl = false;
+        } else {
+          var canvas = document.createElement('canvas');
+          var ctx = canvas.getContext("webgl");
+          if (!ctx) {
+            // 浏览器支持WebGL,但初始化失败。
+            webgl = false;
+          };
+        };
+      }catch(e){
+        webgl = false;
+      };
+    };
+    
+    this.webgl = webgl;
+    
+    // 选择函数
+    if (this.webgl){
+      this.createCanvasObj = this.createCanvasWebGL;
+      this.renderFrame = this.renderFrameWebGL;
+    }else{
+      this.createCanvasObj = this.createCanvasRGB;
+      this.renderFrame = this.renderFrameRGB;
+    };
+    
+    
+    var lastWidth;
+    var lastHeight;
+    var onPictureDecoded = function(buffer, width, height, infos) {
+      self.onPictureDecoded(buffer, width, height, infos);
+      
+      var startTime = nowValue();
+      
+      if (!buffer || !self.render) {
+        return;
+      };
+      
+      self.renderFrame({
+        canvasObj: self.canvasObj,
+        data: buffer,
+        width: width,
+        height: height
+      });
+      
+      if (self.onRenderFrameComplete){
+        self.onRenderFrameComplete({
+          data: buffer,
+          width: width,
+          height: height,
+          infos: infos,
+          canvasObj: self.canvasObj
+        });
+      };
+      
+    };
+    
+    // 提供大小
+    
+    if (!this._config.size){
+      this._config.size = {};
+    };
+    this._config.size.width = this._config.size.width || 200;
+    this._config.size.height = this._config.size.height || 200;
+    
+    if (this._config.useWorker){
+      var worker = new Worker(this._config.workerFile);
+      this.worker = worker;
+      worker.addEventListener('message', function(e) {
+        var data = e.data;
+        if (data.consoleLog){
+          console.log(data.consoleLog);
+          return;
+        };
+        
+        onPictureDecoded.call(self, new Uint8Array(data.buf, 0, data.length), data.width, data.height, data.infos);
+        
+      }, false);
+      
+      worker.postMessage({type: "Broadway.js - Worker init", options: {
+        rgb: !webgl,
+        memsize: this.memsize,
+        reuseMemory: this._config.reuseMemory ? true : false
+      }});
+      
+      if (this._config.transferMemory){
+        this.decode = function(parData, parInfo){
+         
+          
+          worker.postMessage({buf: parData.buffer, offset: parData.byteOffset, length: parData.length, info: parInfo}, [parData.buffer]); // Send data to our worker.
+        };
+        
+      }else{
+        this.decode = function(parData, parInfo){
+          
+          var copyU8 = new Uint8Array(parData.length);
+          copyU8.set( parData, 0, parData.length );
+          worker.postMessage({buf: copyU8.buffer, offset: 0, length: parData.length, info: parInfo}, [copyU8.buffer]); // Send data to our worker.
+        };
+        
+      };
+      
+      if (this._config.reuseMemory){
+        this.recycleMemory = function(parArray){
+          //this.beforeRecycle();
+          worker.postMessage({reuse: parArray.buffer}, [parArray.buffer]); // Send data to our worker.
+          //this.afterRecycle();
+        };
+      }
+      
+    }else{
+      
+      this.decoder = new Decoder({
+        rgb: !webgl
+      });
+      this.decoder.onPictureDecoded = onPictureDecoded;
+
+      this.decode = function(parData, parInfo){
+        self.decoder.decode(parData, parInfo);
+      };
+      
+    };
+    
+    
+    
+    if (this.render){
+      this.canvasObj = this.createCanvasObj({
+        contextOptions: this._config.contextOptions
+      });
+      this.canvas = this.canvasObj.canvas;
+    };
+
+    this.domNode = this.canvas;
+    
+    lastWidth = this._config.size.width;
+    lastHeight = this._config.size.height;
+    
+  };
+  
+  Player.prototype = {
+    
+    onPictureDecoded: function(buffer, width, height, infos){},
+    
+    // call when memory of decoded frames is not used anymore
+    recycleMemory: function(buf){
+    },
+    /*beforeRecycle: function(){},
+    afterRecycle: function(){},*/
+    
+    // for both functions options is:
+    //
+    //  width
+    //  height
+    //  enableScreenshot
+    //
+    // returns a object that has a property canvas which is a html5 canvas
+    createCanvasWebGL: function(options){
+      var canvasObj = this._createBasicCanvasObj(options);
+      canvasObj.contextOptions = options.contextOptions;
+      return canvasObj;
+    },
+    
+    createCanvasRGB: function(options){
+      var canvasObj = this._createBasicCanvasObj(options);
+      return canvasObj;
+    },
+    
+    // part that is the same for webGL and RGB
+    _createBasicCanvasObj: function(options){
+      options = options || {};
+      
+      var obj = {};
+      var width = options.width;
+      if (!width){
+        width = this._config.size.width;
+      };
+      var height = options.height;
+      if (!height){
+        height = this._config.size.height;
+      };
+      obj.canvas = document.createElement('canvas');
+      obj.canvas.width = width;
+      obj.canvas.height = height;
+      obj.canvas.style.backgroundColor = "#0D0E1B";
+      
+      
+      return obj;
+    },
+    
+    // options:
+    //
+    // canvas
+    // data
+    renderFrameWebGL: function(options){
+      
+      var canvasObj = options.canvasObj;
+      
+      var width = options.width || canvasObj.canvas.width;
+      var height = options.height || canvasObj.canvas.height;
+      
+      if (canvasObj.canvas.width !== width || canvasObj.canvas.height !== height || !canvasObj.webGLCanvas){
+        canvasObj.canvas.width = width;
+        canvasObj.canvas.height = height;
+        canvasObj.webGLCanvas = new WebGLCanvas({
+          canvas: canvasObj.canvas,
+          contextOptions: canvasObj.contextOptions,
+          width: width,
+          height: height
+        });
+      };
+      
+      var ylen = width * height;
+      var uvlen = (width / 2) * (height / 2);
+      
+      canvasObj.webGLCanvas.drawNextOutputPicture({
+        yData: options.data.subarray(0, ylen),
+        uData: options.data.subarray(ylen, ylen + uvlen),
+        vData: options.data.subarray(ylen + uvlen, ylen + uvlen + uvlen)
+      });
+      
+      var self = this;
+      self.recycleMemory(options.data);
+      
+    },
+    renderFrameRGB: function(options){
+      var canvasObj = options.canvasObj;
+
+      var width = options.width || canvasObj.canvas.width;
+      var height = options.height || canvasObj.canvas.height;
+      
+      if (canvasObj.canvas.width !== width || canvasObj.canvas.height !== height){
+        canvasObj.canvas.width = width;
+        canvasObj.canvas.height = height;
+      };
+      
+      var ctx = canvasObj.ctx;
+      var imgData = canvasObj.imgData;
+
+      if (!ctx){
+        canvasObj.ctx = canvasObj.canvas.getContext('2d');
+        ctx = canvasObj.ctx;
+
+        canvasObj.imgData = ctx.createImageData(width, height);
+        imgData = canvasObj.imgData;
+      };
+
+      imgData.data.set(options.data);
+      ctx.putImageData(imgData, 0, 0);
+      var self = this;
+      self.recycleMemory(options.data);
+      
+    }
+    
+  };
+  
+  return Player;
+  
+}));
+

+ 526 - 0
static/js/YUVCanvas.js

@@ -0,0 +1,526 @@
+
+
+
+// 通用模块定义
+(function (root, factory) {
+    if (typeof define === 'function' && define.amd) {
+      
+        define([], factory);
+    } else if (typeof exports === 'object') {
+//节点
+        module.exports = factory();
+    } else {
+        // 浏览器全局(根是窗口)
+        root.YUVCanvas = factory();
+    }
+}(this, function () {
+
+
+//此类可用于将输出图片从H264bsdDecoder呈现到画布元素。
+//
+//*如果可用,则使用WebGL呈现内容。
+  function YUVCanvas(parOptions) {
+    
+    parOptions = parOptions || {};
+    
+    this.canvasElement = parOptions.canvas || document.createElement("canvas");
+    this.contextOptions = parOptions.contextOptions;
+    
+    this.type = parOptions.type || "yuv420";
+    
+    this.customYUV444 = parOptions.customYUV444;
+    
+    this.conversionType = parOptions.conversionType || "rec601";
+
+    this.width = parOptions.width || 640;
+    this.height = parOptions.height || 320;
+    
+    this.animationTime = parOptions.animationTime || 0;
+    
+    this.canvasElement.width = this.width;
+    this.canvasElement.height = this.height;
+
+    this.initContextGL();
+
+    if(this.contextGL) {
+      this.initProgram();
+      this.initBuffers();
+      this.initTextures();
+    };
+    
+
+/**
+ * 使用WebGL绘制下一个输出图片
+ */
+    if (this.type === "yuv420"){
+      this.drawNextOuptutPictureGL = function(par) {
+        var gl = this.contextGL;
+        var texturePosBuffer = this.texturePosBuffer;
+        var uTexturePosBuffer = this.uTexturePosBuffer;
+        var vTexturePosBuffer = this.vTexturePosBuffer;
+        
+        var yTextureRef = this.yTextureRef;
+        var uTextureRef = this.uTextureRef;
+        var vTextureRef = this.vTextureRef;
+        
+        var yData = par.yData;
+        var uData = par.uData;
+        var vData = par.vData;
+        
+        var width = this.width;
+        var height = this.height;
+        
+        var yDataPerRow = par.yDataPerRow || width;
+        var yRowCnt     = par.yRowCnt || height;
+        
+        var uDataPerRow = par.uDataPerRow || (width / 2);
+        var uRowCnt     = par.uRowCnt || (height / 2);
+        
+        var vDataPerRow = par.vDataPerRow || uDataPerRow;
+        var vRowCnt     = par.vRowCnt || uRowCnt;
+        
+        gl.viewport(0, 0, width, height);
+
+        var tTop = 0;
+        var tLeft = 0;
+        var tBottom = height / yRowCnt;
+        var tRight = width / yDataPerRow;
+        var texturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, texturePosValues, gl.DYNAMIC_DRAW);
+        
+        if (this.customYUV444){
+          tBottom = height / uRowCnt;
+          tRight = width / uDataPerRow;
+        }else{
+          tBottom = (height / 2) / uRowCnt;
+          tRight = (width / 2) / uDataPerRow;
+        };
+        var uTexturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, uTexturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, uTexturePosValues, gl.DYNAMIC_DRAW);
+        
+        
+        if (this.customYUV444){
+          tBottom = height / vRowCnt;
+          tRight = width / vDataPerRow;
+        }else{
+          tBottom = (height / 2) / vRowCnt;
+          tRight = (width / 2) / vDataPerRow;
+        };
+        var vTexturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, vTexturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, vTexturePosValues, gl.DYNAMIC_DRAW);
+        
+
+        gl.activeTexture(gl.TEXTURE0);
+        gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, yDataPerRow, yRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, yData);
+
+        gl.activeTexture(gl.TEXTURE1);
+        gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, uDataPerRow, uRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, uData);
+
+        gl.activeTexture(gl.TEXTURE2);
+        gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, vDataPerRow, vRowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, vData);
+
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
+      };
+      
+    }else if (this.type === "yuv422"){
+      this.drawNextOuptutPictureGL = function(par) {
+        var gl = this.contextGL;
+        var texturePosBuffer = this.texturePosBuffer;
+        
+        var textureRef = this.textureRef;
+        
+        var data = par.data;
+        
+        var width = this.width;
+        var height = this.height;
+        
+        var dataPerRow = par.dataPerRow || (width * 2);
+        var rowCnt     = par.rowCnt || height;
+
+        gl.viewport(0, 0, width, height);
+
+        var tTop = 0;
+        var tLeft = 0;
+        var tBottom = height / rowCnt;
+        var tRight = width / (dataPerRow / 2);
+        var texturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
+
+        gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+        gl.bufferData(gl.ARRAY_BUFFER, texturePosValues, gl.DYNAMIC_DRAW);
+        
+        gl.uniform2f(gl.getUniformLocation(this.shaderProgram, 'resolution'), dataPerRow, height);
+        
+        gl.activeTexture(gl.TEXTURE0);
+        gl.bindTexture(gl.TEXTURE_2D, textureRef);
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, dataPerRow, rowCnt, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data);
+
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 
+      };
+    };
+    
+  };
+
+  /**
+ * 如果画布支持WebGL,则返回true
+ */
+  YUVCanvas.prototype.isWebGL = function() {
+    return this.contextGL;
+  };
+
+  /**
+ * 从canvas元素创建GL上下文
+ */
+  YUVCanvas.prototype.initContextGL = function() {
+    var canvas = this.canvasElement;
+    var gl = null;
+
+    var validContextNames = ["webgl", "experimental-webgl", "moz-webgl", "webkit-3d"];
+    var nameIndex = 0;
+
+    while(!gl && nameIndex < validContextNames.length) {
+      var contextName = validContextNames[nameIndex];
+
+      try {
+        if (this.contextOptions){
+          gl = canvas.getContext(contextName, this.contextOptions);
+        }else{
+          gl = canvas.getContext(contextName);
+        };
+      } catch (e) {
+        gl = null;
+      }
+
+      if(!gl || typeof gl.getParameter !== "function") {
+        gl = null;
+      }    
+
+      ++nameIndex;
+    };
+
+    this.contextGL = gl;
+  };
+
+/**
+ * 初始化GL着色器程序
+ */
+YUVCanvas.prototype.initProgram = function() {
+    var gl = this.contextGL;
+
+  // 所有类型的顶点着色器都相同
+  var vertexShaderScript;
+  var fragmentShaderScript;
+  
+  if (this.type === "yuv420"){
+
+    vertexShaderScript = [
+      'attribute vec4 vertexPos;',
+      'attribute vec4 texturePos;',
+      'attribute vec4 uTexturePos;',
+      'attribute vec4 vTexturePos;',
+      'varying vec2 textureCoord;',
+      'varying vec2 uTextureCoord;',
+      'varying vec2 vTextureCoord;',
+
+      'void main()',
+      '{',
+      '  gl_Position = vertexPos;',
+      '  textureCoord = texturePos.xy;',
+      '  uTextureCoord = uTexturePos.xy;',
+      '  vTextureCoord = vTexturePos.xy;',
+      '}'
+    ].join('\n');
+    
+    fragmentShaderScript = [
+      'precision highp float;',
+      'varying highp vec2 textureCoord;',
+      'varying highp vec2 uTextureCoord;',
+      'varying highp vec2 vTextureCoord;',
+      'uniform sampler2D ySampler;',
+      'uniform sampler2D uSampler;',
+      'uniform sampler2D vSampler;',
+      'uniform mat4 YUV2RGB;',
+
+      'void main(void) {',
+      '  highp float y = texture2D(ySampler,  textureCoord).r;',
+      '  highp float u = texture2D(uSampler,  uTextureCoord).r;',
+      '  highp float v = texture2D(vSampler,  vTextureCoord).r;',
+      '  gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
+      '}'
+    ].join('\n');
+    
+  }else if (this.type === "yuv422"){
+    vertexShaderScript = [
+      'attribute vec4 vertexPos;',
+      'attribute vec4 texturePos;',
+      'varying vec2 textureCoord;',
+
+      'void main()',
+      '{',
+      '  gl_Position = vertexPos;',
+      '  textureCoord = texturePos.xy;',
+      '}'
+    ].join('\n');
+    
+    fragmentShaderScript = [
+      'precision highp float;',
+      'varying highp vec2 textureCoord;',
+      'uniform sampler2D sampler;',
+      'uniform highp vec2 resolution;',
+      'uniform mat4 YUV2RGB;',
+
+      'void main(void) {',
+      
+      '  highp float texPixX = 1.0 / resolution.x;',
+      '  highp float logPixX = 2.0 / resolution.x;', // half the resolution of the texture
+      '  highp float logHalfPixX = 4.0 / resolution.x;', // half of the logical resolution so every 4th pixel
+      '  highp float steps = floor(textureCoord.x / logPixX);',
+      '  highp float uvSteps = floor(textureCoord.x / logHalfPixX);',
+      '  highp float y = texture2D(sampler, vec2((logPixX * steps) + texPixX, textureCoord.y)).r;',
+      '  highp float u = texture2D(sampler, vec2((logHalfPixX * uvSteps), textureCoord.y)).r;',
+      '  highp float v = texture2D(sampler, vec2((logHalfPixX * uvSteps) + texPixX + texPixX, textureCoord.y)).r;',
+      
+      //'  highp float y = texture2D(sampler,  textureCoord).r;',
+      //'  gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
+      '  gl_FragColor = vec4(y, u, v, 1.0) * YUV2RGB;',
+      '}'
+    ].join('\n');
+  };
+
+  var YUV2RGB = [];
+
+  if (this.conversionType == "rec709") {
+      // ITU-T Rec. 709
+      YUV2RGB = [
+          1.16438,  0.00000,  1.79274, -0.97295,
+          1.16438, -0.21325, -0.53291,  0.30148,
+          1.16438,  2.11240,  0.00000, -1.13340,
+          0, 0, 0, 1,
+      ];
+  } else {
+      // assume ITU-T Rec. 601
+      YUV2RGB = [
+          1.16438,  0.00000,  1.59603, -0.87079,
+          1.16438, -0.39176, -0.81297,  0.52959,
+          1.16438,  2.01723,  0.00000, -1.08139,
+          0, 0, 0, 1
+      ];
+  };
+
+  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
+  gl.shaderSource(vertexShader, vertexShaderScript);
+  gl.compileShader(vertexShader);
+  if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
+    console.log('Vertex shader failed to compile: ' + gl.getShaderInfoLog(vertexShader));
+  }
+
+  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+  gl.shaderSource(fragmentShader, fragmentShaderScript);
+  gl.compileShader(fragmentShader);
+  if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
+    console.log('Fragment shader failed to compile: ' + gl.getShaderInfoLog(fragmentShader));
+  }
+
+  var program = gl.createProgram();
+  gl.attachShader(program, vertexShader);
+  gl.attachShader(program, fragmentShader);
+  gl.linkProgram(program);
+  if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+    console.log('Program failed to compile: ' + gl.getProgramInfoLog(program));
+  }
+
+  gl.useProgram(program);
+
+  var YUV2RGBRef = gl.getUniformLocation(program, 'YUV2RGB');
+  gl.uniformMatrix4fv(YUV2RGBRef, false, YUV2RGB);
+
+  this.shaderProgram = program;
+};
+
+/**
+ * 初始化顶点缓冲区并附加到着色器程序
+ */
+YUVCanvas.prototype.initBuffers = function() {
+  var gl = this.contextGL;
+  var program = this.shaderProgram;
+
+  var vertexPosBuffer = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW);
+
+  var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
+  gl.enableVertexAttribArray(vertexPosRef);
+  gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
+  
+  if (this.animationTime){
+    
+    var animationTime = this.animationTime;
+    var timePassed = 0;
+    var stepTime = 15;
+  
+    var aniFun = function(){
+      
+      timePassed += stepTime;
+      var mul = ( 1 * timePassed ) / animationTime;
+      
+      if (timePassed >= animationTime){
+        mul = 1;
+      }else{
+        setTimeout(aniFun, stepTime);
+      };
+      
+      var neg = -1 * mul;
+      var pos = 1 * mul;
+
+      var vertexPosBuffer = gl.createBuffer();
+      gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
+      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([pos, pos, neg, pos, pos, neg, neg, neg]), gl.STATIC_DRAW);
+
+      var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
+      gl.enableVertexAttribArray(vertexPosRef);
+      gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
+      
+      try{
+        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+      }catch(e){};
+
+    };
+    aniFun();
+    
+  };
+
+  
+
+  var texturePosBuffer = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
+
+  var texturePosRef = gl.getAttribLocation(program, 'texturePos');
+  gl.enableVertexAttribArray(texturePosRef);
+  gl.vertexAttribPointer(texturePosRef, 2, gl.FLOAT, false, 0, 0);
+
+  this.texturePosBuffer = texturePosBuffer;
+
+  if (this.type === "yuv420"){
+    var uTexturePosBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, uTexturePosBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
+
+    var uTexturePosRef = gl.getAttribLocation(program, 'uTexturePos');
+    gl.enableVertexAttribArray(uTexturePosRef);
+    gl.vertexAttribPointer(uTexturePosRef, 2, gl.FLOAT, false, 0, 0);
+
+    this.uTexturePosBuffer = uTexturePosBuffer;
+    
+    
+    var vTexturePosBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vTexturePosBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
+
+    var vTexturePosRef = gl.getAttribLocation(program, 'vTexturePos');
+    gl.enableVertexAttribArray(vTexturePosRef);
+    gl.vertexAttribPointer(vTexturePosRef, 2, gl.FLOAT, false, 0, 0);
+
+    this.vTexturePosBuffer = vTexturePosBuffer;
+  };
+
+};
+
+/**
+ * 初始化GL纹理并附加两个着色器应用程序
+ */
+YUVCanvas.prototype.initTextures = function() {
+  var gl = this.contextGL;
+  var program = this.shaderProgram;
+
+  if (this.type === "yuv420"){
+
+    var yTextureRef = this.initTexture();
+    var ySamplerRef = gl.getUniformLocation(program, 'ySampler');
+    gl.uniform1i(ySamplerRef, 0);
+    this.yTextureRef = yTextureRef;
+
+    var uTextureRef = this.initTexture();
+    var uSamplerRef = gl.getUniformLocation(program, 'uSampler');
+    gl.uniform1i(uSamplerRef, 1);
+    this.uTextureRef = uTextureRef;
+
+    var vTextureRef = this.initTexture();
+    var vSamplerRef = gl.getUniformLocation(program, 'vSampler');
+    gl.uniform1i(vSamplerRef, 2);
+    this.vTextureRef = vTextureRef;
+    
+  }else if (this.type === "yuv422"){
+    // only one texture for 422
+    var textureRef = this.initTexture();
+    var samplerRef = gl.getUniformLocation(program, 'sampler');
+    gl.uniform1i(samplerRef, 0);
+    this.textureRef = textureRef;
+
+  };
+};
+
+/**
+ * 创建和配置单个纹理
+ */
+YUVCanvas.prototype.initTexture = function() {
+    var gl = this.contextGL;
+
+    var textureRef = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, textureRef);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+    gl.bindTexture(gl.TEXTURE_2D, null);
+
+    return textureRef;
+};
+
+//将图片数据绘制到画布上。
+//如果此对象使用WebGL,则数据必须是I420格式的ArrayBuffer,
+//否则,数据必须是RGBA格式的ArrayBuffer。
+YUVCanvas.prototype.drawNextOutputPicture = function(width, height, croppingParams, data) {
+    var gl = this.contextGL;
+
+    if(gl) {
+        this.drawNextOuptutPictureGL(width, height, croppingParams, data);
+    } else {
+        this.drawNextOuptutPictureRGBA(width, height, croppingParams, data);
+    }
+};
+
+
+
+/**
+ *在二维画布上使用ARGB数据绘制下一个输出图片.
+ */
+YUVCanvas.prototype.drawNextOuptutPictureRGBA = function(width, height, croppingParams, data) {
+    var canvas = this.canvasElement;
+
+    var croppingParams = null;
+
+    var argbData = data;
+
+    var ctx = canvas.getContext('2d');
+    var imageData = ctx.getImageData(0, 0, width, height);
+    imageData.data.set(argbData);
+
+    if(croppingParams === null) {
+        ctx.putImageData(imageData, 0, 0);
+    } else {
+        ctx.putImageData(imageData, -croppingParams.left, -croppingParams.top, 0, 0, croppingParams.width, croppingParams.height);
+    }
+};
+  
+  return YUVCanvas;
+  
+}));

+ 298 - 0
static/js/aa.js

@@ -0,0 +1,298 @@
+//画布
+var canvas;
+var context;
+//蒙版
+var canvas_bak;
+var context_bak;
+
+var canvasWidth = 720;
+var canvasHeight = 1280;
+
+var canvasTop;
+var canvasLeft;
+
+//画笔大小
+var size = 1;
+var color = '#000000';
+var resolving
+//			            var query = window.location.search.substring(1);
+//			          var vars = query.split("&");
+//			          var data = {}
+//			var clientType = vars.find(e => {
+//              return e.startsWith('clientType')
+//          })
+//			var cardIp = vars.find(e => {
+//              return e.startsWith('cardIp')
+//          })
+//			var port = vars.find(e => {
+//              return e.startsWith('port')
+//          })
+//			
+//			var sn = vars.find(e => {
+//              return e.startsWith('sn')
+//          })
+//			 var data = {}         
+//            data.clientType=clientType.substring(11, clientType.length)
+//            
+//            data.cardIp=cardIp.substring(7, cardIp.length)
+//            
+//            data.port=port.substring(5, port.length)
+//            
+//            data.sn=sn.substring(3, sn.length)
+//var wsss = new WebSocket("ws://192.168.128.254:8022/controlWebSocket?"+"clientType="+data.clientType+"&cardIp="+data.cardIp+"&port="+data.port+"&sn="+data.sn);
+//
+
+
+var wsss = new WebSocket("ws://192.168.128.254:8022/controlWebSocket?clientType=0&cardIp=192.168.128.106&port=9100&sn=RK3923C1201900079&demoTime=300");
+
+wsss.onopen = function() {
+	var pings = {
+		"event": "getScreenStatus"
+	}
+	wsss.send(JSON.stringify(pings));
+
+};
+wsss.onmessage = function(event) {
+	var resets = JSON.parse(event.data)
+
+	resolving = resets.data.orientation
+	console.log('>>>', resolving)
+	if(resolving == 1) {
+
+		canvas_bak = document.getElementsByTagName("canvas");
+
+	} else {
+		canvas_bak = document.getElementById("mocan");
+	}
+
+	if(resolving == 1) {
+		$('#mocan').remove()
+		$('canvas').css({
+			"display": "block",
+			"width": "100%",
+			"height": "100%",
+			"position": "absolute",
+			"top": "0px",
+			"left": "0px",
+			"z-index": "999"
+		})
+		$('#mainScreen-main').css({"display": "block"})
+	} else {
+
+		$('canvas').css({
+			"display": "block",
+			"width": "153%",
+			"height": "162%",
+			"position": "absolute",
+			"top": "-171px",
+			"left": "-94px",
+			"transform": "rotate(-90deg)"
+		})
+		$('#mainScreen-main').css({"display": "block"})
+		$('#no-ne').css({
+			"width": "901px",
+			"height": "555px",
+			"position": "absolute",
+			"top": "0",
+			"left": "-269px",
+			"background": "#000000",
+			"z-index": "99999",
+			"font-size": "18px",
+			"color": "#FFFFFF",
+			"text-align": "center",
+			
+		})
+		$('.no-ne-text').css({
+			"margin-top": "24%",
+		})
+	}
+	canvas_bak.width = canvasWidth;
+	canvas_bak.height = canvasHeight;
+	canvas = document.getElementById("mainScreen-main");
+	canvasTop = $(canvas_bak).offset().top
+	canvasLeft = $(canvas_bak).offset().left;
+	//			context_bak = canvas_bak.getContext('2d');		
+	$(canvas_bak).css("z-index", 999);
+};
+wsss.onclose = function(event) {
+
+};
+wsss.onerror = function(event) {
+
+};
+
+//画图形
+var draw_graph = function(graphType, obj) {
+
+	//把蒙版放于画板上面
+	//$("#canvas_bak").css("z-index",1);
+	$("#container").css("z-index", 30);
+	$("#dedit").css("z-index", 20);
+	//先画在蒙版上 再复制到画布上
+
+	chooseImg(obj);
+	var canDraw = false;
+
+	var startX;
+	var startY;
+
+	//鼠标按下获取 开始xy开始画图
+	var mousedown = function(e) {
+		// 
+		//横屏
+		if(resolving == 1) {
+//			var ping = {
+//				"data": {
+//					"fingerList": [{
+//						"action": 0,
+//						"x": e.offsetX * 2,
+//						"y": e.offsetY * 2.3
+//					}]
+//				},
+//				"event": "0"
+//			}
+			var ping = {"data":{"action":0,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"0"}
+		} else if(resolving == 0) {
+//			var ping = {
+//				"data": {
+//					"fingerList": [{
+//						"action": 0,
+//						"x": e.offsetX * 1.422,
+//						"y": e.offsetY * 1.3
+//					}]
+//				},
+//				"event": "0"
+//			}
+			var ping = {"data":{"action":0,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"0"}
+		}
+
+		wsss.send(JSON.stringify(ping));
+
+		e = e || window.event;
+		/*startX = e.clientX - canvasLeft;
+		startY = e.clientY - canvasTop;*/
+		//	    console.log('鼠标按下获取:x',e.clientX-canvasLeft,'y:',e.clientY - canvasTop)
+		console.log('---当前的偏移-:x', resolving) //offsetX
+		console.log('11111:x', e.clientX, '2222222y:', e.clientY) //offsetX
+		console.log('offsetX:x', e.offsetX * 1.422, 'offsetY:', e.offsetY * 1.3) //offsetX
+		console.log(e)
+		canDraw = true;
+
+	};
+
+	//鼠标离开 把蒙版canvas的图片生成到canvas中
+	var mouseup = function(e) {
+
+		e = e || window.event;
+		//		startX = e.clientX - canvasLeft;
+		//		startY = e.clientY - canvasTop;
+		//		console.log('鼠标离开>>>',e.clientX - canvasLeft)
+		if(resolving == 1) {
+			var ping = {
+				"data": {
+					"fingerList": [{
+						"action": 0,
+						"x": e.offsetX * 2,
+						"y": e.offsetY * 2.3
+					}]
+				},
+				"event": "1"
+			}
+			
+			var ping =  {"data":{"action":1,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"1"}
+		} else if(resolving == 0) {
+//			var ping = {
+//				"data": {
+//					"fingerList": [{
+//						"action": 0,
+//						"x": e.offsetX * 1.422,
+//						"y": e.offsetY * 1.3
+//					}]
+//				},
+//				"event": "1"
+//			}
+			
+			var ping =  {"data":{"action":1,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"1"}
+		}
+
+		wsss.send(JSON.stringify(ping));
+		canDraw = false;
+
+	};
+
+	//清空层 云手机超出屏幕的开关
+	var clearContext = function(type) {
+		canDraw = false;
+	}
+
+	// 鼠标移动
+	var mousemove = function(e) {
+		//		console.log('鼠标移动7>>>','X:',e.clientX,'Y:',e.clientY)
+		e = e || window.event;
+		var x = e.clientX - canvasLeft;
+		var y = e.clientY - canvasTop;
+		//方块  4条直线搞定
+		if(graphType == 'square') {
+			if(canDraw) {}
+			//直线
+		} else if(graphType == 'line') {} else if(graphType == 'pencil') {
+			if(canDraw) {
+
+				//				context_bak.lineTo(e.clientX   - canvasLeft ,e.clientY  - canvasTop);
+				//				context_bak.stroke();	
+				if(resolving == 1) {
+//					var ping = {
+//						"data": {
+//							"fingerList": [{
+//								"action": 0,
+//								"x": e.offsetX * 2,
+//								"y": e.offsetY * 2.3
+//							}]
+//						},
+//						"event": "2"
+//					}
+					var ping = {"data":{"action":2,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"2"}
+				} else if(resolving == 0) {
+//					var ping = {
+//						"data": {
+//							"fingerList": [{
+//								"action": 0,
+//								"x": e.offsetX * 1.422,
+//								"y": e.offsetY * 1.3
+//							}]
+//						},
+//						"event": "2"
+//					}
+					
+					var ping = {"data":{"action":2,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"2"}
+				}
+				wsss.send(JSON.stringify(ping));
+			}
+			//圆 未画得时候 出现一个小圆
+		} else if(graphType == 'circle') {} else if(graphType == 'handwriting') {
+			var hwSize = 1;
+			if(canDraw) {} else {}
+			//橡皮擦 不管有没有在画都出现小方块 按下鼠标 开始清空区域
+		} else if(graphType == 'rubber') {}
+	};
+
+	//鼠标离开区域以外 除了涂鸦 都清空
+	var mouseout = function() {
+
+		if(graphType != 'handwriting') {
+			clearContext();
+
+		}
+	}
+
+	$(canvas_bak).unbind();
+	$(canvas_bak).bind('mousedown', mousedown);
+	$(canvas_bak).bind('mousemove', mousemove);
+	$(canvas_bak).bind('mouseup', mouseup);
+	$(canvas_bak).bind('mouseout', mouseout);
+}
+
+//选择功能按钮 修改样式
+function chooseImg(obj) {
+
+}

File diff suppressed because it is too large
+ 4557 - 0
static/js/aac.js


File diff suppressed because it is too large
+ 4022 - 0
static/js/aurora.js


+ 95 - 0
static/js/auroraplayer.js

@@ -0,0 +1,95 @@
+UNKNOWN_ART = '/dgplayer/resources/fallback_album_art.png';
+console.log("走到DGAuroraPlayer1");
+
+function DGAuroraPlayer(player, DGPlayer) {
+	console.log("走到DGAuroraPlayer2");
+	this.player = player;
+	this.ui = DGPlayer;
+
+	DGPlayer.seekTime = 0;
+	DGPlayer.duration = 0;
+	DGPlayer.bufferProgress = 0;
+
+	var onplay, onpause, onvolume, onformat, onbuffer, onprogress, onduration, onmetadata;
+
+	DGPlayer.on('play', onplay = function() {
+		alert()
+		console.log(111111111111111111111111111111)
+		player.play();
+		DGPlayer.state = 'playing';
+	});
+
+	DGPlayer.on('pause', onpause = function() {
+		console.log(22222222222222)
+		player.pause();
+		DGPlayer.state = 'paused';
+	});
+
+	DGPlayer.on('volume', onvolume = function(value) {
+		console.log(1)
+		console.log(value)
+		player.volume = value;
+	});
+
+	player.on('buffer', onbuffer = function(percent) {
+		console.log(1)
+		DGPlayer.bufferProgress = percent;
+	});
+
+	player.on('progress', onprogress = function(time) {
+		console.log(1)
+		DGPlayer.seekTime = time;
+	});
+
+	player.on('duration', onduration = function(duration) {
+		console.log(1)
+		DGPlayer.duration = duration;
+	});
+
+	player.on('metadata', onmetadata = function(data) {
+		console.log(1)
+		DGPlayer.songTitle = data.title;
+		DGPlayer.songArtist = data.artist;
+
+		if (data.coverArt) {
+			DGPlayer.coverArt = data.coverArt.toBlobURL();
+		} else {
+			DGPlayer.coverArt = UNKNOWN_ART;
+		}
+	});
+
+	var originalDescription = DGPlayer.fileDescription;
+	player.on('error', onerror = function(e) {
+		// reset state
+		DGPlayer.state = 'paused';
+		DGPlayer.duration = 0;
+		DGPlayer.bufferProgress = 0;
+		DGPlayer.seekTime = 0;
+		DGPlayer.coverArt = UNKNOWN_ART;
+		DGPlayer.songTitle = 'Unknown Title';
+		DGPlayer.songArtist = 'Unknown Artist';
+
+		DGPlayer.fileDescription = "Hmm. I don't recognize that format. Try another.";
+		setTimeout(function() {
+			console.log(1)
+			DGPlayer.fileDescription = originalDescription;
+		}, 3000);
+	});
+
+	player.volume = DGPlayer.volume;
+	player.play();
+	DGPlayer.state = 'playing';
+
+	this.disconnect = function() {
+		if (player) player.stop();
+
+		DGPlayer.off('play', onplay);
+		DGPlayer.off('pause', onpause);
+		DGPlayer.off('volume', onvolume);
+		player.off('buffer', onbuffer);
+		player.off('format', onformat);
+		player.off('progress', onprogress);
+		player.off('duration', onduration);
+		player.off('metadata', onmetadata);
+	}
+}

BIN
static/js/avc.wasm


+ 270 - 0
static/js/carousel.js

@@ -0,0 +1,270 @@
+(function(window, undefined) {
+    var Carousel = function(ele, obj) {
+        console.log(obj)
+        this.ele = ele;
+        this.cardsList = this.ele.children();
+        this.cardsNum = this.cardsList.length;
+        this.direction = obj.direction ? obj.direction : 'horizontal';
+        this.scale = obj.scale;
+        this.transition = obj.transition || '500ms';
+        this.transformOrigin = obj.transformOrigin;
+        this.opacity = obj.opacity;
+        this.offsetDistance = obj.offsetDistance;
+        this.switchBtn = obj.switchBtn;
+        this.isClickCard = obj.isClickCard || false;
+        this.isAuto = obj.isAuto || false;
+        this.interval = obj.interval || 5000;
+        this.n = obj.n;
+        this.mediant = Math.floor(this.cardsNum / 2);
+        this.cardsListArr = [].slice.call(this.cardsList);
+        this.timer = null;
+        this.cssObj = {};
+        this.showPicNumber = obj.showPicNumber || null;
+        this.certainStyle();
+        this.switchEffect();
+        this.cardsClick();
+        this.switchBtnClick();
+        this.autoMove();
+        this.switchTimer();
+        this.dataList = obj.dataList;
+        this.nav = obj.nav;
+    };
+    Carousel.prototype = {
+        constructor: Carousel,
+        switchTimer: function() {
+            var carousel = this;
+            if (this.isAuto) {
+                this.cardsList.on('mouseover', function() {
+                    clearInterval(carousel.timer);
+                });
+                this.cardsList.on('mouseout', function() {
+                    carousel.autoMove();
+                });
+            };
+        },
+        certainStyle: function() {
+            this.cssObj.position = 'absolute';
+            if (this.scale) {
+                this.scale.length == 1 && this.scale.push(this.scale[0]);
+            };
+            if (this.direction == 'horizontal') {
+
+                this.cssObj.left = '50%';
+                this.availSize = this.ele.outerWidth();
+                this.cardSize = this.cardsList.eq(0).outerWidth();
+
+            } else if (this.direction == 'vertical') {
+                this.cssObj.top = '50%';
+                this.availSize = this.ele.outerHeight();
+                this.cardSize = this.cardsList.eq(0).outerHeight();
+                //				console.log(this.cssObj)
+            };
+            this.offsetDistance = this.offsetDistance || this.availSize / (this.cardsNum - 1);
+            this.transformOrigin && (this.cssObj.transformOrigin = this.transformOrigin);
+            this.cssObj.transition = this.transition;
+            //			console.log(this.cssObj)
+        },
+        dynamicStyle: function(offsetIndex, offsetIndexAbs, reset, showPicNumber) {
+            if (this.direction == 'horizontal') {
+                //				console.log(this.cssObj)
+                // console.log(this.cardSize, this.offsetDistance, offsetIndex, "this.cardSize")
+                // console.log(window.innerWidth, "innerWidth")
+                let arrLength = this.cardsListArr.length;
+                // 根据轮播图的长度和屏幕宽度做相应偏移量调整
+                switch (arrLength) {
+                    case 2:
+                        {
+                            if (window.innerWidth < 768 && offsetIndex !== 0) {
+								if(offsetIndex > 0){
+									this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance / 2 * offsetIndex + (-offsetIndex) * 170 + 'px';
+								}else{
+									this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance / 2 * offsetIndex + (-offsetIndex) * 167 + 'px';
+								}
+                            } else if (window.innerWidth < 1200 && offsetIndex !== 0) {
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance / 2 * offsetIndex + (-offsetIndex) * 60 + 'px';
+                            } else if (window.innerWidth >= 1200 && offsetIndex !== 0) {
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance / 2 * offsetIndex + (-offsetIndex) * 10 + 'px';
+                            } else {
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance * offsetIndex + 'px';
+                            }
+                        };
+                        break;
+                    case 3:
+                    case 4:
+                        {
+                            if (window.innerWidth < 768 && offsetIndex !== 0) {
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance / 2 * offsetIndex + (-offsetIndex) * 15 + 'px';
+                            } else if (window.innerWidth < 1200 && offsetIndex !== 0) {
+                                if (offsetIndex == -1) {
+                                    this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance * offsetIndex + 52 + 'px';
+                                } else {
+                                    this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance * offsetIndex - 60 + 'px';
+                                }
+                            } else if (window.innerWidth >= 1200 && offsetIndex !== 0) {
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance * offsetIndex + (-offsetIndex) * 10 + 'px';
+                            } else {
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance * offsetIndex + 'px';
+                            }
+                        };
+                        break;
+                    default:
+                        {
+                            if (window.innerWidth < 768) {
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance * offsetIndex + (-offsetIndex) * 4 + 'px';
+                            } else if(window.innerWidth < 1200) {
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance * offsetIndex + 'px';
+                            }else{
+                                this.cssObj.marginLeft = -this.cardSize / 2 + this.offsetDistance * offsetIndex + (offsetIndex) * 30 + 'px';
+							}
+                        };
+                        break;
+                }
+
+            } else if (this.direction == 'vertical') {
+
+                this.cssObj.marginTop = -this.cardSize / 2 + this.offsetDistance * offsetIndex + 'px';
+            };
+            this.cssObj.zIndex = reset;
+            // this.opacity && (this.cssObj.opacity = Math.pow(this.opacity, offsetIndexAbs));
+            // 根据要展示的图片数,来给定透明度,showPicNumber为1时展示主图,为3时展示3张图,不传时则默认所有都展示,其它则不展示
+            if (this.opacity) {
+                switch (showPicNumber) {
+                    case 1:
+                        {
+                            if (Math.pow(this.opacity, offsetIndexAbs) === 1) {
+                                this.cssObj.opacity = 1;
+                            } else {
+                                this.cssObj.opacity = 0;
+                            }
+                        };
+                        break;
+                    case 3:
+                        {
+                            if (Math.pow(this.opacity, offsetIndexAbs) >= 0.9) {
+                                this.cssObj.opacity = Math.pow(this.opacity, offsetIndexAbs)
+                            } else {
+                                this.cssObj.opacity = 0
+                            }
+                        };
+                        break;
+                    default:
+                        this.cssObj.opacity = Math.pow(this.opacity, offsetIndexAbs);
+                        break;
+                }
+            }
+            this.scale && (this.cssObj.transform = 'scale(' + Math.pow(this.scale[0], offsetIndexAbs) + ',' + Math.pow(this.scale[1], offsetIndexAbs) + ')');
+            this.cssObj.background = "rgba(0,0,0,1);"
+            var show = "box-shadow"
+            this.cssObj.show = '0px 8px 13px 0px rgba(23,28,46,0.88)'
+            console.log(this.scale[1])
+                //		          if(this.opacity == 0.9){
+                //		          	this.cssObj.background = 'red';
+                //		          }
+                //              	this.cssObj.background = 'red';
+
+        },
+        switchEffect: function() {
+            var carousel = this;
+            const showPicNumber = carousel.showPicNumber;
+            var offsetNum = Math.abs(carousel.n - carousel.mediant);
+            console.log('arousel.n>>>', carousel.n)
+            console.log("carousel.mediant>>>", carousel.mediant)
+            if (carousel.n == carousel.mediant && carousel.nav == 1) {
+
+                return;
+            } else if (carousel.n > carousel.mediant) {
+                //				alert("提示信息2")
+                carousel.cardsListArr = carousel.cardsListArr.concat(carousel.cardsListArr.splice(0, offsetNum));
+            } else {
+                //				alert("提示信息3")
+                carousel.cardsListArr = carousel.cardsListArr.splice(carousel.cardsNum - offsetNum).concat(carousel.cardsListArr);
+            };
+            $(carousel.cardsListArr).each(function(i, e) {
+                var offsetIndex = i - carousel.mediant,
+                    offsetIndexAbs = Math.abs(offsetIndex),
+                    reset = carousel.mediant - offsetIndexAbs;
+                carousel.dynamicStyle(offsetIndex, offsetIndexAbs, reset, showPicNumber);
+                //			    console.log(carousel.cssObj)
+                $(e).css(carousel.cssObj);
+                $(e).attr('n', i);
+            });
+        },
+        cardsClick: function() {
+            console.log(">>>>>>>>>s", this.isClickCard)
+            if (this.isClickCard) {
+
+                var carousel = this;
+
+
+                $(carousel.cardsListArr).on('click', function() {});
+
+
+
+                //				$('.nav-gse').on('click',function(){
+                //					$(this).addClass('nav-gse-ave')
+                //					$(this).siblings().removeClass('nav-gse-ave')
+                ////					css({"background":"red"})
+                //					$(this).find('.nav-bg').find('.nav-mnai').removeClass('nav-mnai')
+                //					$(this).siblings().find('.nav-bg').find('.nav-buseqw').addClass('nav-mnai')
+                //					carousel.switchEffect();
+                //				})
+            };
+        },
+        prev: function() {
+            var carousel = this;
+            carousel.n = carousel.mediant - 1;
+
+            carousel.n < 0 && (carousel.n = carousel.cardsNum - 1);
+            carousel.switchEffect();
+
+            //			$("#containerse li").each(function(i, e) {
+            //				if($(e).css("opacity") == 1){
+            //					indexs = i
+            //				}
+            //			});
+            //		  
+            //			console.log("dataList>>>",carousel.dataList)
+        },
+        next: function() {
+
+            var carousel = this;
+            carousel.n = carousel.mediant + 1;
+            carousel.n > carousel.cardsNum - 1 && (carousel.n = 0);
+            carousel.switchEffect();
+        },
+        switchBtnClick: function() {
+            var carousel = this;
+
+            if (carousel.switchBtn) {
+                carousel.switchBtn.eq(0).on('click', function() {
+                    carousel.prev();
+                    if (carousel.isAuto) {
+                        clearInterval(carousel.timer);
+                        carousel.cardsList.eq(carousel.n).one('transitionend', function() {
+                            carousel.autoMove();
+                        });
+                    };
+                });
+                carousel.switchBtn.eq(1).on('click', function() {
+                    carousel.next();
+                    if (carousel.isAuto) {
+                        clearInterval(carousel.timer);
+                        carousel.cardsList.eq(carousel.n).one('transitionend', function() {
+                            carousel.autoMove();
+                        });
+                    };
+                });
+            };
+        },
+        autoMove: function() {
+            var carousel = this;
+            if (carousel.isAuto) {
+                clearInterval(carousel.timer);
+                carousel.timer = setInterval(function() {
+                    carousel.next();
+                }, carousel.interval);
+            };
+        },
+    };
+    window.Carousel = Carousel;
+}(window));

+ 48 - 0
static/js/classlist.js

@@ -0,0 +1,48 @@
+
+
+if (!("classList" in document.documentElement) && Object.defineProperty && typeof HTMLElement !== 'undefined') {
+    Object.defineProperty(HTMLElement.prototype, 'classList', {
+        get: function() {
+            var self = this;
+            function update(fn) {
+                return function(value) {
+                    var classes = self.className.split(/\s+/),
+                        index = classes.indexOf(value);
+
+                    fn(classes, index, value);
+                    self.className = classes.join(" ");
+                }
+            }
+
+            var ret = {                    
+                add: update(function(classes, index, value) {
+                    ~index || classes.push(value);
+                }),
+
+                remove: update(function(classes, index) {
+                    ~index && classes.splice(index, 1);
+                }),
+
+                toggle: update(function(classes, index, value) {
+                    ~index ? classes.splice(index, 1) : classes.push(value);
+                }),
+
+                contains: function(value) {
+                    return !!~self.className.split(/\s+/).indexOf(value);
+                },
+
+                item: function(i) {
+                    return self.className.split(/\s+/)[i] || null;
+                }
+            };
+            
+            Object.defineProperty(ret, 'length', {
+                get: function() {
+                    return self.className.split(/\s+/).length;
+                }
+            });
+
+            return ret;
+        }
+    });
+}

+ 309 - 0
static/js/draw.js

@@ -0,0 +1,309 @@
+//画布
+var canvas;
+var context;
+//蒙版
+var canvas_bak;
+var context_bak;
+
+var canvasWidth = 720;
+var canvasHeight = 1280;
+
+var canvasTop;
+var canvasLeft;
+
+//画笔大小
+var size = 1;
+var color = '#000000';
+var resolving
+
+
+
+
+                       var url = window.location.href;
+                       url = url.split('/')
+                       var baseUrl =url[2]
+			           var query = window.location.search.substring(1);
+			          var vars = query.split("&");
+			          var data = {}
+			var clientType = vars.find(e => {
+                return e.startsWith('clientType')
+            })|| ''
+			var cardIp = vars.find(e => {
+                return e.startsWith('cardIp')
+            }) || ''
+			var port = vars.find(e => {
+                return e.startsWith('port')
+            })|| ''
+			
+			var sn = vars.find(e => {
+                return e.startsWith('sn')
+            })|| ''
+			var username = vars.find(e => {
+				return e.startsWith('username')
+			})|| ''
+			var userCardId = vars.find(e => {
+				return e.startsWith('userCardId')
+			})|| ''
+			 var data = {}         
+              data.clientType=clientType.substring(11, clientType.length)
+              
+              data.cardIp=cardIp.substring(7, cardIp.length)
+              
+              data.port=port.substring(5, port.length)
+              data.sn=sn.substring(3, sn.length)
+			  
+			  data.username =username.substring(9, username.length)
+			  data.userCardId =userCardId.substring(11, userCardId.length)
+              // var urlss= url[2]  //'14.215.128.96'
+			  var urlss = 'test.androidscloud.com'
+			  var cUrl = data.clientType === 3? "ws://"+urlss+"/authControlWebSocket?"+"clientType="+data.clientType+"&username="+data.username+"&userCardId="+data.userCardId : "ws://"+urlss+"/controlWebSocket?"+"clientType="+data.clientType+"&cardIp="+data.cardIp+"&port="+data.port+"&sn="+data.sn
+			  // var cUrl = "ws://14.215.128.96//controlWebSocket?clientType=1&sn=RK3930C2301900045&cardIp=14.215.128.96&port=2045"
+var wsss = new WebSocket(cUrl);
+
+
+
+//var wsss = new WebSocket("ws://14.215.128.96/controlWebSocket?clientType=0&cardIp=30.30.30.58&port=9100&sn=RK3930C2301900060");
+
+wsss.onopen = function() {
+	var pings = {
+		"event": "getScreenStatus"
+	}
+	wsss.send(JSON.stringify(pings));
+   var bitRate ={"data":{"bitRate":1000},"event":"bitRate"}
+     wsss.send(JSON.stringify(bitRate));
+};
+
+wsss.onmessage = function(event) {
+	var resets = JSON.parse(event.data)
+
+	resolving = resets.data.orientation
+	console.log('>>>resolvingresolvingresolving', resolving)
+	
+	
+	
+         
+			
+	
+	
+	if(resolving == 1) {
+
+		canvas_bak = document.getElementsByTagName("canvas");
+
+	} else {
+		canvas_bak = document.getElementsByClassName("mocan");
+	}
+	
+	
+	
+
+	if(resolving == 1) {
+
+		$('#mocan').removeClass('mocan')
+		$('#mainScreen-main').addClass('mainScreen-main')
+		$('.mainScreen-main').on('click', function() {
+			 
+				//		    	console.log(this)
+				draw_graph('pencil', this)
+
+			
+
+			})
+		$('canvas').css({
+			"display": "block",
+			"width": "100%",
+			"height": "100%",
+			"position": "absolute",
+			"top": "0px",
+			"left": "0px",
+			"z-index": "999",
+			"transform": "rotate(0deg)"
+		})
+		$('#mainScreen-main').css({"display": "block"})
+	} else {
+//      $("#mainScreen-main").
+$('#mainScreen-main').removeClass('mainScreen-main')
+$('#mocan').addClass('mocan')
+
+
+
+
+$('.mocan').on('click', function() {
+			 
+				//		    	console.log(this)
+				draw_graph('pencil', this)
+
+			
+
+			})
+
+
+
+
+
+
+		$('canvas').css({
+			"display": "block",
+			"width": "153%",
+			"height": "162%",
+			"position": "absolute",
+			"top": "-171px",
+			"left": "-94px",
+			"z-index": "0",
+			"transform": "rotate(-90deg)"
+		})
+		$('#mainScreen-main').css({"display": "block"})
+		$('#no-ne').css({
+			"width": "901px",
+			"height": "555px",
+			"position": "absolute",
+			"top": "0",
+			"left": "-269px",
+			"background": "#000000",
+			"z-index": "99999",
+			"font-size": "18px",
+			"color": "#FFFFFF",
+			"text-align": "center",
+			
+		})
+		$('.no-ne-text').css({
+			"margin-top": "24%",
+		})
+	}
+	
+
+	//			context_bak = canvas_bak.getContext('2d');		
+	$(canvas_bak).css("z-index", 999);
+};
+
+
+
+wsss.onclose = function(event) {
+
+};
+wsss.onerror = function(event) {
+
+};
+
+//画图形
+var draw_graph = function(graphType, obj) {
+
+	//把蒙版放于画板上面
+	//$("#canvas_bak").css("z-index",1);
+	$("#container").css("z-index", 30);
+	$("#dedit").css("z-index", 20);
+	//先画在蒙版上 再复制到画布上
+
+	chooseImg(obj);
+	var canDraw = false;
+
+	var startX;
+	var startY;
+
+	//鼠标按下获取 开始xy开始画图
+	var mousedown = function(e) {
+		
+		
+			var pingssfe = {
+		      "event": "getScreenStatus"
+	        }
+			wsss.send(JSON.stringify(pingssfe));
+		
+		// 
+		//横屏
+		if(resolving == 1) {
+			var ping = {"data":{"action":0,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"0"}
+			 console.log("黄飞111》》》")
+			
+		} else if(resolving == 0) {
+			var ping ={"data":{"action":0,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"0"}
+	
+		 console.log("黄飞222》》》")
+		
+		}
+  
+		wsss.send(JSON.stringify(ping));
+
+  
+		e = e || window.event;
+		/*startX = e.clientX - canvasLeft;
+		startY = e.clientY - canvasTop;*/
+		//	    console.log('鼠标按下获取:x',e.clientX-canvasLeft,'y:',e.clientY - canvasTop)
+		
+		canDraw = true;
+
+	};
+
+	//鼠标离开 把蒙版canvas的图片生成到canvas中
+	var mouseup = function(e) {
+
+		e = e || window.event;
+		//		startX = e.clientX - canvasLeft;11111
+		//		startY = e.clientY - canvasTop;
+		//		console.log('鼠标离开>>>',e.clientX - canvasLeft)
+		if(resolving == 1) {
+			var ping = {"data":{"action":1,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"1"}
+		} else if(resolving == 0) {
+			var ping = {"data":{"action":1,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"1"}
+		}
+
+		wsss.send(JSON.stringify(ping));
+		// var seets = {"event":"getScreenStatus"}
+		//   wsss.send(JSON.stringify(seets));
+		canDraw = false;
+
+	};
+
+	//清空层 云手机超出屏幕的开关
+	var clearContext = function(type) {
+		canDraw = false;
+	}
+
+	// 鼠标移动
+	var mousemove = function(e) {
+		//		console.log('鼠标移动7>>>','X:',e.clientX,'Y:',e.clientY)
+		e = e || window.event;
+
+		//方块  4条直线搞定
+		if(graphType == 'square') {
+			if(canDraw) {}
+			//直线
+		} else if(graphType == 'line') {} else if(graphType == 'pencil') {
+			if(canDraw) {
+
+				//				context_bak.lineTo(e.clientX   - canvasLeft ,e.clientY  - canvasTop);
+				//				context_bak.stroke();	
+				if(resolving == 1) {
+					var ping = {"data":{"action":2,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"2"}
+				} else if(resolving == 0) {
+					var ping = {"data":{"action":2,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"2"}
+				}
+				wsss.send(JSON.stringify(ping));
+			}
+			//圆 未画得时候 出现一个小圆
+		} else if(graphType == 'circle') {} else if(graphType == 'handwriting') {
+			var hwSize = 1;
+			if(canDraw) {} else {}
+			//橡皮擦 不管有没有在画都出现小方块 按下鼠标 开始清空区域
+		} else if(graphType == 'rubber') {}
+	};
+
+	//鼠标离开区域以外 除了涂鸦 都清空
+	var mouseout = function() {
+
+		if(graphType != 'handwriting') {
+			clearContext();
+
+		}
+	}
+
+	$(canvas_bak).unbind();
+	$(canvas_bak).bind('mousedown', mousedown);
+	$(canvas_bak).bind('mousemove', mousemove);
+	$(canvas_bak).bind('mouseup', mouseup);
+	$(canvas_bak).bind('mouseout', mouseout);
+}
+
+//选择功能按钮 修改样式
+function chooseImg(obj) {
+
+}

+ 298 - 0
static/js/draw1.js

@@ -0,0 +1,298 @@
+//画布
+var canvas;
+var context;
+//蒙版
+var canvas_bak;
+var context_bak;
+
+var canvasWidth = 720;
+var canvasHeight = 1280;
+
+var canvasTop;
+var canvasLeft;
+
+//画笔大小
+var size = 1;
+var color = '#000000';
+var resolving
+
+
+
+
+                       var url = window.location.href;
+                       url = url.split('/')
+                       var baseUrl =url[2]
+			           var query = window.location.search.substring(1);
+			          var vars = query.split("&");
+			          var data = {}
+			var clientType = vars.find(e => {
+                return e.startsWith('clientType')
+            })
+			var cardIp = vars.find(e => {
+                return e.startsWith('cardIp')
+            })
+			var port = vars.find(e => {
+                return e.startsWith('port')
+            })
+			
+			var sn = vars.find(e => {
+                return e.startsWith('sn')
+            })
+			 var data = {}         
+              data.clientType=clientType.substring(11, clientType.length)
+              
+              data.cardIp=cardIp.substring(7, cardIp.length)
+              
+              data.port=port.substring(5, port.length)
+              
+              data.sn=sn.substring(3, sn.length)
+              var urlss= "192.168.31.14" //url[2]  //'14.215.128.96'
+var wsss = new WebSocket("wss://"+urlss+"/controlWebSocket?"+"clientType="+data.clientType+"&cardIp="+data.cardIp+"&port="+data.port+"&sn="+data.sn);
+
+
+
+//var wsss = new WebSocket("ws://14.215.128.96/controlWebSocket?clientType=0&cardIp=30.30.30.58&port=9100&sn=RK3930C2301900060");
+
+wsss.onopen = function() {
+	var pings = {
+		"event": "getScreenStatus"
+	}
+	wsss.send(JSON.stringify(pings));
+   var bitRate ={"data":{"bitRate":1000},"event":"bitRate"}
+     wsss.send(JSON.stringify(bitRate));
+};
+
+wsss.onmessage = function(event) {
+	var resets = JSON.parse(event.data)
+
+	resolving = resets.data.orientation
+	console.log('>>>', resolving)
+	
+	
+	
+         
+			
+	
+	
+	if(resolving == 1) {
+
+		canvas_bak = document.getElementsByTagName("canvas");
+
+	} else {
+		canvas_bak = document.getElementsByClassName("mocan");
+	}
+	
+	
+	
+
+	if(resolving == 1) {
+
+		$('#mocan').removeClass('mocan')
+		$('#mainScreen-main').addClass('mainScreen-main')
+		$('.mainScreen-main').on('click', function() {
+			 
+				//		    	console.log(this)
+				draw_graph('pencil', this)
+
+			
+
+			})
+		$('canvas').css({
+			"display": "block",
+			"width": "100%",
+			"height": "100%",
+			"position": "absolute",
+			"top": "0px",
+			"left": "0px",
+			"z-index": "999",
+			"transform": "rotate(0deg)"
+		})
+		$('#mainScreen-main').css({"display": "block"})
+	} else {
+//      $("#mainScreen-main").
+$('#mainScreen-main').removeClass('mainScreen-main')
+$('#mocan').addClass('mocan')
+
+
+
+
+$('.mocan').on('click', function() {
+			 
+				//		    	console.log(this)
+				draw_graph('pencil', this)
+
+			
+
+			})
+
+
+
+
+
+
+		$('canvas').css({
+			"display": "block",
+			"width": "153%",
+			"height": "162%",
+			"position": "absolute",
+			"top": "-171px",
+			"left": "-94px",
+			"z-index": "0",
+			"transform": "rotate(-90deg)"
+		})
+		$('#mainScreen-main').css({"display": "block"})
+		$('#no-ne').css({
+			"width": "901px",
+			"height": "555px",
+			"position": "absolute",
+			"top": "0",
+			"left": "-269px",
+			"background": "#000000",
+			"z-index": "99999",
+			"font-size": "18px",
+			"color": "#FFFFFF",
+			"text-align": "center",
+			
+		})
+		$('.no-ne-text').css({
+			"margin-top": "24%",
+		})
+	}
+	
+
+	//			context_bak = canvas_bak.getContext('2d');		
+	$(canvas_bak).css("z-index", 999);
+};
+
+
+
+wsss.onclose = function(event) {
+
+};
+wsss.onerror = function(event) {
+
+};
+
+//画图形
+var draw_graph = function(graphType, obj) {
+
+	//把蒙版放于画板上面
+	//$("#canvas_bak").css("z-index",1);
+	$("#container").css("z-index", 30);
+	$("#dedit").css("z-index", 20);
+	//先画在蒙版上 再复制到画布上
+
+	chooseImg(obj);
+	var canDraw = false;
+
+	var startX;
+	var startY;
+
+	//鼠标按下获取 开始xy开始画图
+	var mousedown = function(e) {
+		
+		
+			var pingssfe = {
+		      "event": "getScreenStatus"
+	        }
+			wsss.send(JSON.stringify(pingssfe));
+		
+		// 
+		//横屏
+		if(resolving == 1) {
+			var ping = {"data":{"action":0,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"0"}
+			 console.log("黄飞111》》》")
+			
+		} else if(resolving == 0) {
+			var ping ={"data":{"action":0,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"0"}
+	
+		 console.log("黄飞222》》》")
+		
+		}
+  
+		wsss.send(JSON.stringify(ping));
+
+  
+		e = e || window.event;
+		/*startX = e.clientX - canvasLeft;
+		startY = e.clientY - canvasTop;*/
+		//	    console.log('鼠标按下获取:x',e.clientX-canvasLeft,'y:',e.clientY - canvasTop)
+		
+		canDraw = true;
+
+	};
+
+	//鼠标离开 把蒙版canvas的图片生成到canvas中
+	var mouseup = function(e) {
+
+		e = e || window.event;
+		//		startX = e.clientX - canvasLeft;11111
+		//		startY = e.clientY - canvasTop;
+		//		console.log('鼠标离开>>>',e.clientX - canvasLeft)
+		if(resolving == 1) {
+			var ping = {"data":{"action":1,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"1"}
+		} else if(resolving == 0) {
+			var ping = {"data":{"action":1,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"1"}
+		}
+
+		wsss.send(JSON.stringify(ping));
+		// var seets = {"event":"getScreenStatus"}
+		//   wsss.send(JSON.stringify(seets));
+		canDraw = false;
+
+	};
+
+	//清空层 云手机超出屏幕的开关
+	var clearContext = function(type) {
+		canDraw = false;
+	}
+
+	// 鼠标移动
+	var mousemove = function(e) {
+		//		console.log('鼠标移动7>>>','X:',e.clientX,'Y:',e.clientY)
+		e = e || window.event;
+
+		//方块  4条直线搞定
+		if(graphType == 'square') {
+			if(canDraw) {}
+			//直线
+		} else if(graphType == 'line') {} else if(graphType == 'pencil') {
+			if(canDraw) {
+
+				//				context_bak.lineTo(e.clientX   - canvasLeft ,e.clientY  - canvasTop);
+				//				context_bak.stroke();	
+				if(resolving == 1) {
+					var ping = {"data":{"action":2,"count":1,"pointerId":0,"x":e.offsetX * 2,"y":e.offsetY * 2.3},"event":"2"}
+				} else if(resolving == 0) {
+					var ping = {"data":{"action":2,"count":1,"pointerId":0,"x":e.offsetX * 1.422,"y":e.offsetY * 1.3},"event":"2"}
+				}
+				wsss.send(JSON.stringify(ping));
+			}
+			//圆 未画得时候 出现一个小圆
+		} else if(graphType == 'circle') {} else if(graphType == 'handwriting') {
+			var hwSize = 1;
+			if(canDraw) {} else {}
+			//橡皮擦 不管有没有在画都出现小方块 按下鼠标 开始清空区域
+		} else if(graphType == 'rubber') {}
+	};
+
+	//鼠标离开区域以外 除了涂鸦 都清空
+	var mouseout = function() {
+
+		if(graphType != 'handwriting') {
+			clearContext();
+
+		}
+	}
+
+	$(canvas_bak).unbind();
+	$(canvas_bak).bind('mousedown', mousedown);
+	$(canvas_bak).bind('mousemove', mousemove);
+	$(canvas_bak).bind('mouseup', mouseup);
+	$(canvas_bak).bind('mouseout', mouseout);
+}
+
+//选择功能按钮 修改样式
+function chooseImg(obj) {
+
+}

+ 1 - 0
static/js/jquery-1.10.2.js

@@ -0,0 +1 @@
+document.write("<script src='https://libs.baidu.com/jquery/1.10.2/jquery.min.js'><\/script>");

File diff suppressed because it is too large
+ 4 - 0
static/js/jquery-1.11.0.min.js


File diff suppressed because it is too large
+ 6 - 0
static/js/jquery.min.js


+ 366 - 0
static/js/players.js

@@ -0,0 +1,366 @@
+
+//云手机事件的相关逻辑 aac解码
+console.log("走到DGPlayer1");
+function DGPlayer(root) {
+ 
+console.log("走到DGPlayer2");
+ var events = {},
+     state = 'paused';
+ 
+
+ new Image().src = "/dgplayer/resources/playbutton_active.png";
+ new Image().src = "/dgplayer/resources/pausebutton.png";
+ new Image().src = "/dgplayer/resources/pausebutton_active.png";
+ new Image().src = "/dgplayer/resources/choosefile_pressed.png";
+ 
+ // 阻止IE中的文本选择
+ root.onselectstart = function() {
+     return false
+ }
+ 
+ var seekBar = (function() {
+     
+     var loading = root.querySelector(".seek .track .loaded"),
+         progress = root.querySelector(".seek .track .progress"),
+         played = root.querySelector(".seek span:first-child"),
+         remaining = root.querySelector(".seek span:last-child"),
+         maxWidth = loading.parentNode.offsetWidth - 2,
+         loaded = 0, currentTime = 0, trackLength = 0, oldSeconds = 0;
+         
+         
+     function pad(input) {
+         return ("00" + input).slice(-2);
+     }
+     
+     return {
+         getTrackLength: function() {
+             return trackLength;
+         },
+
+         setTrackLength: function(time) {
+             trackLength = time;
+             this.seekTime = currentTime;
+         },
+
+         getCurrentTime: function() {
+             return currentTime;
+         },
+
+         setCurrentTime: function(time) {
+             oldSeconds = Math.floor(currentTime / 1000 % 60);;
+             currentTime = time;
+             
+             if (currentTime >= trackLength && trackLength > 0)
+                 emit("pause");
+
+             var t = currentTime / 1000,
+                 seconds = Math.floor(t % 60),
+                 minutes = Math.floor((t /= 60) % 60);
+                 
+             if (seconds === oldSeconds)
+                 return;
+             
+             played.innerHTML = minutes + ':' + pad(seconds);
+             
+             // 如果我们知道持续时间,只显示进度条和剩余时间
+             if (trackLength > 0) {
+                 var r = (trackLength - currentTime) / 1000,
+                     remainingSeconds = Math.floor(r % 60),
+                     remainingMinutes = Math.floor((r /= 60) % 60);
+                 
+                 remaining.innerHTML = '-' + remainingMinutes + ':' + pad(remainingSeconds);
+                 position = Math.max(0, Math.min(1, currentTime / trackLength));
+                 progress.style.width = maxWidth * position + 'px';
+             } else {
+                 remaining.innerHTML = '-0:00';
+             }
+         },
+         
+         getAmountLoaded: function() {
+             return loaded;
+         },
+         
+         setAmountLoaded: function(val) {
+             loaded = Math.max(0, Math.min(100, val));
+             loading.style.width = maxWidth * (loaded / 100) + 'px';
+         }
+     }
+     
+ })();
+     
+ var playpause = (function() {
+     
+     var button = root.querySelector(".button"),
+         interval = null, playing = false;
+         
+     button.onclick = function() {
+         emit(playing ? "pause" : "play");
+     };
+
+     root.addEventListener('keyup', function(e) {
+         e.which === 32 && emit(playing ? "pause" : "play");
+     });
+     
+     function setPlaying(play) {
+         if (playing = play)
+             button.classList.add("pause");
+         else
+             button.classList.remove("pause");
+     }
+     
+     return {
+         setPlaying: setPlaying,
+         getPlaying: function() {
+             return playing;
+         }
+     }
+     
+ })();
+ 
+ var slider = (function() {
+     
+     var handle = root.querySelector(".volume .handle"),
+         progress = root.querySelector(".volume .progress"),
+         track = root.querySelector(".volume .track")
+         volumeLeft = root.querySelector(".volume img:first-child"),
+         volumeRight = root.querySelector(".volume img:last-child");
+         
+     var lastY = 0, 
+         down = false,
+         height = 65,
+         handleSize = 20,
+         min = -8,
+         max = height - handleSize / 2 - 3,
+         curY = Math.floor(height / 2 - handleSize / 2),
+         value = 50;
+         
+     function update(dontEmit) {
+         if ('webkitTransform' in handle.style)
+             handle.style.webkitTransform = "translate3d(0, " + (-max - min + curY) + "px" + ", 0)";
+         else
+             handle.style.bottom = max + min - curY + "px";
+
+         progress.style.height = max - curY + "px";
+         value = Math.round(100 - (curY - min) / (max - min) * 100);
+         
+         if (!dontEmit)
+             emit("volume", value);
+     }
+     update();
+     
+     handle.onmousedown = handle.ontouchstart = function(e) {
+         lastY = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
+         down = true;
+         e.stopPropagation();
+         handle.classList.add("active");
+         e.preventDefault();
+     }
+     
+     function onMove(e) {
+         var eventY = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
+         var y = Math.max(min, Math.min(max, curY + eventY - lastY));
+         if (!down || y === curY) return;
+
+         curY = y;
+         lastY = eventY;
+         update();
+     }
+     
+     function onUp(e) {
+         if(!down) return;
+         down = false;
+         handle.classList.remove("active");
+     }
+     
+     document.addEventListener("mousemove", onMove, false);
+     document.addEventListener("touchmove", onMove, false);
+     document.addEventListener("mouseup", onUp, false);
+     document.addEventListener("touchend", onUp, false);
+     
+     // Handle clicking on the minimum and maximum volume icons
+     function animate() {
+         handle.classList.add("animatable");
+         progress.classList.add("animatable");
+
+         update();
+
+         setTimeout(function() {
+             handle.classList.remove("animatable");
+             progress.classList.remove("animatable");
+         }, 250);
+     }
+     
+     volumeLeft.onclick = function() {
+         curY = min;
+         animate();
+     }
+
+     volumeRight.onclick = function() {
+         curY = max;
+         animate();
+     }
+     
+     // 控制点击轨迹
+     track.onmousedown = track.ontouchstart = function(e) {
+         var y = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
+         
+         // 得到轨道的绝对偏移量
+         var offset = 0, obj = track;
+         while (obj) {
+             offset += obj.offsetTop - obj.scrollTop;
+             obj = obj.offsetParent;
+         }
+         
+         curY = Math.max(min, Math.min(max, y - offset - (handleSize + min)));
+         handle.onmousedown(e);
+         update();
+     }
+     
+     return {
+         getValue: function() {
+             return value;
+         },
+         
+         setValue: function(val) {
+             val = Math.max(0, Math.min(100, val));
+             curY = max - (val / 100) * (max - min);
+             update(true);
+         }
+     }
+     
+ })();
+ 
+ var filebutton = (function() {
+     
+     var button = root.querySelector('.file_button'),
+         input = document.createElement('input');
+         
+     input.setAttribute('type', 'file');
+     input.style.opacity = 0;
+     input.style.position = 'absolute';
+     input.style.left = '-1000px';
+     
+     input.onchange = function(e) {
+         emit('file', input.files[0]);
+     }
+     
+     button.onclick = function() {
+         input.click();
+		 console.log("bbbbbbbbbbbbb");
+     }
+     
+ })();
+ 
+ function emit(event) {
+     if (!events[event]) return;
+     
+     var args = Array.prototype.slice.call(arguments, 1),
+         callbacks = events[event];
+         
+     for (var i = 0, len = callbacks.length; i < len; i++) {
+         callbacks[i].apply(null, args);
+     }
+ } 
+ 
+ var API = {
+     on: function(event, fn) {
+         events[event] || (events[event] = []);
+         events[event].push(fn);
+     },
+     
+     off: function(event, fn) {
+         var eventsOf = events[event],
+             index = eventsOf.indexOf(fn);
+             
+         ~index && eventsOf.splice(index, 1);
+     }
+ };
+ 
+ // Object.defineProperty Opera垫片
+ Object.defineProperty || (Object.defineProperty = function(obj, prop, config) {
+     if (config.get && obj.__defineGetter__)
+         obj.__defineGetter__(prop, config.get);
+         
+     if (config.set && obj.__defineSetter__)
+         obj.__defineSetter__(prop, config.set);
+ })
+ 
+ Object.defineProperty(API, "bufferProgress", {
+     get: seekBar.getAmountLoaded,
+     set: seekBar.setAmountLoaded
+ });
+ 
+ Object.defineProperty(API, "state", {
+     set: function(newstate) {
+         playpause.setPlaying(newstate == 'playing' || newstate == 'buffering');                
+         state = newstate;
+     },
+     
+     get: function() { 
+         return state;
+     }
+ });
+ 
+ Object.defineProperty(API, "duration", {
+     get: seekBar.getTrackLength,
+     set: seekBar.setTrackLength
+ });
+ 
+ Object.defineProperty(API, "seekTime", {
+     get: seekBar.getCurrentTime,
+     set: seekBar.setCurrentTime
+ });
+ 
+ Object.defineProperty(API, "volume", {
+     get: slider.getValue,
+     set: slider.setValue
+ });
+ 
+ var img = root.querySelector(".avatar img");
+ Object.defineProperty(API, "coverArt", {
+     get: function() {
+         return img.src;
+     },
+     
+     set: function(src) {
+         img.src = src;
+     }
+ });
+ 
+ var title = root.querySelector("span.title"),
+     artist = root.querySelector("span.artist");
+     
+ Object.defineProperty(API, "songTitle", {
+     get: function() {
+         return title.innerHTML;
+     },
+     
+     set: function(val) {
+         title.innerHTML = val;
+     }
+ });
+ 
+ Object.defineProperty(API, "songArtist", {
+     get: function() {
+         return artist.innerHTML;
+     },
+     
+     set: function(val) {
+         artist.innerHTML = val;
+     }
+ });
+ 
+ var description = root.querySelector('.file_description');
+ Object.defineProperty(API, "fileDescription", {
+     get: function() {
+         return description.innerHTML;
+     },
+     
+     set: function(val) {
+         description.innerHTML = val;
+     }
+ });
+ 
+ return API;
+ 
+}

File diff suppressed because it is too large
+ 4663 - 0
static/js/szxcode.js


+ 100 - 0
static/js/web.js

@@ -0,0 +1,100 @@
+//应模块主要作用是 ws链接进行,发送到解码模块
+//了解当前模块请搜索关键字 》》》TDDE《《《 了解注意注释
+(function() {
+	var e = {}.hasOwnProperty,
+		t = function(t, r) {
+			function o() {
+				this.constructor = t
+			}
+			for (var n in r) e.call(r, n) && (t[n] = r[n]);
+			return o.prototype = r.prototype, t.prototype = new o, t.__super__ = r.prototype, t
+		};
+	AV.WebSocketSource = function(e) {
+		function r(e, t) {
+			return this.serverUrl = e, this.fileName = t, "undefined" == typeof WebSocket || null === WebSocket ? this.emit(
+				"error", "此浏览器不支持WebSocket.") : (this.socket = new WebSocket(this.serverUrl), null ==
+				this.socket.binaryType ? (this.socket.close(), this.emit("error",
+					"此浏览器不支持二进制WebSocket.")) : (this.bytesLoaded = 0, this._setupSocket(), void 0))
+		}
+		return t(r, e), r.prototype.start = function() {
+						return this._send(JSON.stringify({
+							resume: !0
+						}))
+		}, r.prototype.pause = function() {
+			return
+		}, r.prototype.reset = function() {
+			return this._send(JSON.stringify({
+				reset: !0
+			}))
+		}, r.prototype._send = function(e) {
+			return this.open ? this.socket.send(e) : this._bufferMessage = e
+		}, r.prototype._setupSocket = function() {
+			var e = this;
+			return this.socket.binaryType = "arraybuffer", 
+			this.socket.onopen = function() {
+				return e.open = !0, e.fileName && e.socket.send(JSON.stringify({
+					fileName: e.fileName
+				})), e._bufferMessage ? (e.socket.send(e._bufferMessage), e._bufferMessage = null) : void 0
+			}, 
+			this.socket.onmessage = function(t) {
+				var r, o;
+				r = new AV.Buffer(new Uint8Array(o))
+				var se = t.data
+				//TDDE 这里是发送每一帧到decode
+				// console.log("这里是发送每一帧到decode",new Uint8Array(se));
+				if (new Uint8Array(se)[0] == 0) {
+
+					var messageData = new Uint8Array(se)
+					player.decode(messageData); //视频播放
+					console.log('黄飞5')
+					return
+				} else if (new Uint8Array(se)[1] == 241) {
+
+					return o = t.data, "string" != typeof o ? (r = new AV.Buffer(new Uint8Array(o)), e.bytesLoaded += r.length, e.length &&
+						e.emit("progress", 100 * (e.bytesLoaded / e.length)), e.emit("data", r)) : (o = JSON.parse(o), null != o.fileSize ?
+						e.length = o.fileSize : null != o.error ? e.emit("error", o.error) : o.end ? e.socket.close() : void 0)
+				} else {
+					var ssep = JSON.parse(se)
+					if (ssep.errorCode == 8006) {
+						alert(ssep.errorMsg)
+					} else if (ssep.errorCode == 8007) {
+						alert(ssep.errorMsg)
+					} else if (ssep.errorCode == 8008) {
+						alert(ssep.errorMsg)
+					} else if (ssep.errorCode == 8009) {
+						alert(ssep.errorMsg)
+					} else if (ssep.errorCode == 8010) {
+						alert(ssep.errorMsg)
+					} else if (ssep.errorCode == 8003) {
+						console.log("分享过期啦========")
+
+						$(".leftmains").css({
+							"right": "0"
+						})
+						$('.leftmains').show()
+						$('.bottommains').show()
+						$('#btnMuted').show()
+						alert(ssep.errorMsg)
+					}
+				}
+			}, this.socket.onclose = function(t) {
+				//			 	 console.log('黄飞5')
+				return e.open = !1, t.wasClean ? e.emit("end") : e.emit("error", "WebSocket closed uncleanly with code " + t.code +
+					".")
+			}, this.socket.onerror = function(t) {
+				alert("你访问的屏幕已经过期")
+				console.log('黄飞>>>6', t)
+				return e.emit("error", t)
+			}
+		}, r
+	}(AV.EventEmitter), AV.Asset.fromWebSocket = function(e, t) {
+		var r;
+		console.log('黄飞1')
+		return r = new AV.WebSocketSource(e, t), new AV.Asset(r)
+
+	}, AV.Player.fromWebSocket = function(e, t) {
+		var r;
+		console.log('黄飞2')
+		return r = AV.Asset.fromWebSocket(e, t), new AV.Player(r)
+	}
+}).call(this);

+ 68 - 0
static/js/webapk.js

@@ -0,0 +1,68 @@
+(function() {
+	var e = {}.hasOwnProperty,
+		t = function(t, r) {
+			function o() {
+				this.constructor = t
+			}
+			for(var n in r) e.call(r, n) && (t[n] = r[n]);
+			return o.prototype = r.prototype, t.prototype = new o, t.__super__ = r.prototype, t
+		};
+	AV.WebSocketSource = function(e) {
+		function r(e, t) {
+			return this.serverUrl = e, this.fileName = t, "undefined" == typeof WebSocket || null === WebSocket ? this.emit("error", "This browser does not have WebSocket support.") : (this.socket = new WebSocket(this.serverUrl), null == this.socket.binaryType ? (this.socket.close(), this.emit("error", "This browser does not have binary WebSocket support.")) : (this.bytesLoaded = 0, this._setupSocket(), void 0))
+		}
+		return t(r, e), r.prototype.start = function() {
+//			return this._send(JSON.stringify({
+//				resume: !0
+//			}))
+		}, r.prototype.pause = function() {
+			return 
+		}, r.prototype.reset = function() {
+			return this._send(JSON.stringify({
+				reset: !0
+			}))
+		}, r.prototype._send = function(e) {
+			return this.open ? this.socket.send(e) : this._bufferMessage = e
+		}, r.prototype._setupSocket = function() {
+			var e = this;
+			return this.socket.binaryType = "arraybuffer", this.socket.onopen = function() {
+				return e.open = !0, e.fileName && e.socket.send(JSON.stringify({
+					fileName: e.fileName
+				})), e._bufferMessage ? (e.socket.send(e._bufferMessage), e._bufferMessage = null) : void 0
+			}, this.socket.onmessage = function(t) {
+				var r, o;
+               r = new AV.Buffer(new Uint8Array(o))
+               var se = t.data
+				
+				if(new Uint8Array(se)[0] == 0){
+					
+//      var messageData = new Uint8Array(se) 
+//    player.decode(messageData);
+//                  console.log('黄飞5')
+					return
+				}else{
+//					console.log('黄飞6')
+//					console.log('黄飞2',new Uint8Array(se)[0])
+					return o = t.data, "string" != typeof o ? (r = new AV.Buffer(new Uint8Array(o)), e.bytesLoaded += r.length, e.length && e.emit("progress", 100 * (e.bytesLoaded / e.length)), e.emit("data", r)) : (o = JSON.parse(o), null != o.fileSize ? e.length = o.fileSize : null != o.error ? e.emit("error", o.error) : o.end ? e.socket.close() : void 0)
+				}
+				 
+			
+			 }, this.socket.onclose = function(t) {
+			 	 console.log('黄飞5')
+				return e.open = !1, t.wasClean ? e.emit("end") : e.emit("error", "WebSocket closed uncleanly with code " + t.code + ".")
+			}, this.socket.onerror = function(t) {
+				console.log('黄飞6')
+				return e.emit("error", t)
+			}
+		}, r
+	}(AV.EventEmitter), AV.Asset.fromWebSocket = function(e, t) {
+		var r;
+		console.log('黄飞1')
+		return r = new AV.WebSocketSource(e, t), new AV.Asset(r)
+		
+	}, AV.Player.fromWebSocket = function(e, t) {
+		var r;
+		console.log('黄飞2')
+		return r = AV.Asset.fromWebSocket(e, t), new AV.Player(r)
+	}
+}).call(this);

+ 218 - 0
static/src/controller/buffer-controller.js

@@ -0,0 +1,218 @@
+/*
+ * Buffer Controller
+*/
+
+import Event from '../events';
+import EventHandler from '../event-handler';
+ 
+class BufferController extends EventHandler {
+
+  constructor(wfs) {
+    super(wfs,
+      Event.MEDIA_ATTACHING,
+      Event.BUFFER_APPENDING,
+      Event.BUFFER_RESET
+    );
+    
+    this.mediaSource = null;
+    this.media = null;
+    this.pendingTracks = {};
+    this.sourceBuffer = {};
+    this.segments = [];
+ 
+    this.appended = 0;
+    this._msDuration = null;
+
+    // Source Buffer listeners
+    this.onsbue = this.onSBUpdateEnd.bind(this);
+
+    this.browserType = 0;
+    if (navigator.userAgent.toLowerCase().indexOf('firefox') !== -1){
+      this.browserType = 1;
+    }
+    this.mediaType = 'H264Raw';
+
+    this.websocketName = undefined; 
+    this.channelName = undefined;
+  }
+
+  destroy() {
+    EventHandler.prototype.destroy.call(this);
+  }
+ 
+  onMediaAttaching(data) {
+    let media = this.media = data.media;
+    this.mediaType = data.mediaType;
+    this.websocketName = data.websocketName;
+    this.channelName = data.channelName;
+    if (media) {
+      // setup the media source
+      var ms = this.mediaSource = new MediaSource();
+      //Media Source listeners
+      this.onmso = this.onMediaSourceOpen.bind(this);
+      this.onmse = this.onMediaSourceEnded.bind(this);
+      this.onmsc = this.onMediaSourceClose.bind(this);
+      ms.addEventListener('sourceopen', this.onmso);
+      ms.addEventListener('sourceended', this.onmse);
+      ms.addEventListener('sourceclose', this.onmsc);
+      // link video and media Source
+      media.src = URL.createObjectURL(ms);
+    }
+  }
+
+  onMediaDetaching() {
+ 
+  }
+   
+  onBufferAppending(data) { 
+    if (!this.segments) {
+      this.segments = [ data ];
+    } else {
+      this.segments.push(data); 
+    }
+    this.doAppending(); 
+  }
+  
+  onMediaSourceClose() {
+    console.log('media source closed');
+  }
+
+  onMediaSourceEnded() {
+    console.log('media source ended');
+  }
+
+  onSBUpdateEnd(event) { 
+    // Firefox
+    if (this.browserType === 1){
+      this.mediaSource.endOfStream();
+      this.media.play();  
+    }
+
+    console.log("currentTime: " + this.media.currentTime);
+    var buffered = this.sourceBuffer['video'].buffered;
+    var played   = this.media.played;
+    for(var j = 0; j < played.length; j++){
+	console.log("played start: " + played.start(j) );
+	console.log("played end: " + played.end(j) );
+    }
+    console.log("readystate: " + this.media.readyState);
+    for(var i=0; i< buffered.length; i++){
+	console.log("start: " + buffered.start(i) );
+	console.log("end: " + buffered.end(i));
+    	//this.media.currentTime = buffered.end(i); 
+    }
+
+    this.appending = false;
+    this.doAppending();
+    this.updateMediaElementDuration();
+  }
+ 
+  updateMediaElementDuration() {
+  
+  }
+
+  onMediaSourceOpen() { 
+    let mediaSource = this.mediaSource;
+    if (mediaSource) {
+      // once received, don't listen anymore to sourceopen event
+      mediaSource.removeEventListener('sourceopen', this.onmso);
+    }
+
+    if (this.mediaType === 'FMp4'){ 
+      this.checkPendingTracks();
+    }
+
+    this.wfs.trigger(Event.MEDIA_ATTACHED, {media:this.media, channelName:this.channelName, mediaType: this.mediaType, websocketName:this.websocketName});
+  }
+
+  checkPendingTracks() {  
+    this.createSourceBuffers({ tracks : 'video' , mimeType:'' } );
+    this.pendingTracks = {};  
+  }
+
+  onBufferReset(data) { 
+    if (this.mediaType === 'H264Raw'){ 
+      this.createSourceBuffers({ tracks : 'video' , mimeType: data.mimeType } );
+    }
+  }
+ 
+  createSourceBuffers(tracks) {
+    var sourceBuffer = this.sourceBuffer,mediaSource = this.mediaSource;
+    let mimeType;
+    if (tracks.mimeType === ''){
+      mimeType = 'video/mp4;codecs=avc1.420028'; // avc1.42c01f avc1.42801e avc1.640028 avc1.420028
+    }else{
+      mimeType = 'video/mp4;codecs=' + tracks.mimeType;
+    }
+ 
+    try {
+      let sb = sourceBuffer['video'] = mediaSource.addSourceBuffer(mimeType);
+      sb.addEventListener('updateend', this.onsbue);
+      track.buffer = sb;
+    } catch(err) {
+
+    }
+    this.wfs.trigger(Event.BUFFER_CREATED, { tracks : tracks } );
+    this.media.play();    
+  }
+
+  doAppending() {
+   
+    var wfs = this.wfs, sourceBuffer = this.sourceBuffer, segments = this.segments;
+    if (Object.keys(sourceBuffer).length) {
+       
+      if (this.media.error) {
+        this.segments = [];
+        console.log('trying to append although a media error occured, flush segment and abort');
+        return;
+      }
+      if (this.appending) { 
+        return;
+      }
+         
+      if (segments && segments.length) { 
+        var segment = segments.shift();
+	//console.log("segments len: " + segments.length + " segment len: " + segment.data.length);
+        try {
+          if(sourceBuffer[segment.type]) { 
+            this.parent = segment.parent;
+            sourceBuffer[segment.type].appendBuffer(segment.data);
+            this.appendError = 0;
+            this.appended++;
+            this.appending = true;
+          } else {
+  
+          }
+        } catch(err) {
+          // in case any error occured while appending, put back segment in segments table 
+          segments.unshift(segment);
+          var event = {type: ErrorTypes.MEDIA_ERROR};
+          if(err.code !== 22) {
+            if (this.appendError) {
+              this.appendError++;
+            } else {
+              this.appendError = 1;
+            }
+            event.details = ErrorDetails.BUFFER_APPEND_ERROR;
+            event.frag = this.fragCurrent;   
+            if (this.appendError > wfs.config.appendErrorMaxRetry) { 
+              segments = [];
+              event.fatal = true;    
+              return;
+            } else {
+              event.fatal = false; 
+            }
+          } else { 
+            this.segments = [];
+            event.details = ErrorDetails.BUFFER_FULL_ERROR; 
+            return;
+          } 
+        }
+        
+      }
+    }
+  }
+ 
+}
+
+export default BufferController;

+ 138 - 0
static/src/controller/flow-controller.js

@@ -0,0 +1,138 @@
+/*
+ * Flow Controller
+*/
+ 
+import Event from '../events';
+import EventHandler from '../event-handler'; 
+
+class FlowController extends EventHandler {
+
+  constructor(wfs) {
+    super(wfs,
+      Event.MEDIA_ATTACHED,
+      Event.BUFFER_CREATED,
+      Event.FILE_PARSING_DATA,
+      Event.FILE_HEAD_LOADED,
+      Event.FILE_DATA_LOADED,
+      Event.WEBSOCKET_ATTACHED,
+      Event.FRAG_PARSING_DATA,
+      Event.FRAG_PARSING_INIT_SEGMENT);
+    
+    this.fileStart = 0;
+    this.fileEnd = 0;
+    this.pendingAppending = 0;
+    this.mediaType = undefined; 
+    channelName:this.channelName;
+  }
+
+  destroy() {
+     EventHandler.prototype.destroy.call(this);
+  }  
+
+  onMediaAttached(data) {      
+    if (data.websocketName != undefined){
+    	
+    	     	var query = window.location.search.substring(1);
+							var vars = query.split("&");
+							var data = {}
+							var url = window.location.href;
+			                      url = url.split('/')
+										var clientType = vars.find(e => {
+							              return e.startsWith('clientType')
+							          })
+										var cardIp = vars.find(e => {
+							              return e.startsWith('cardIp')
+							          })
+										var port = vars.find(e => {
+							              return e.startsWith('port')
+							          })
+										
+										var sn = vars.find(e => {
+							              return e.startsWith('sn')
+							          })
+										var demoTime = vars.find(e => {
+							              return e.startsWith('demoTime')
+							          })
+										 var data = {}         
+							            data.clientType=clientType.substring(11, clientType.length)
+							            
+							            data.cardIp=cardIp.substring(7, cardIp.length)
+							            
+							            data.port=port.substring(5, port.length)
+							            
+							            data.sn=sn.substring(3, sn.length)
+							            
+							            data.demoTime=demoTime.substring(9, demoTime.length)
+							    	
+							    	console.log(data)
+							    	
+
+							//var client = new WebSocket("wss://xcx.androidscloud.com/videoWebSocket?clientType=0&cardIp=30.30.30.24&port=9100&sn=RK3930C2301900042");
+                     var urlss = url[2]
+      	
+        //var client = new WebSocket('ws://192.168.128.254:8022/videoWebSocket?'+"clientType="+data.clientType+"&cardIp="+data.cardIp+"&port="+data.port+"&sn="+data.sn);
+        
+      var client = new WebSocket("ws://" + urlss + '/videoWebSocket?' + "clientType=" + data.clientType +"&cardIp=" + data.cardIp + "&port=" + data.port + "&sn=" + data.sn);
+     
+//    var protocol = 'binary';
+//    var client = new WebSocket(uri,protocol);
+      this.wfs.attachWebsocket(client,data.channelName);
+    }else{
+       console.log('websocketName ERROE!!!');
+    }
+
+  }
+  
+  onBufferCreated(data) {
+    this.mediaType = data.mediaType; 
+  }
+
+  onFileHeadLoaded(data) { 
+  }
+
+  onFileDataLoaded(data) { 
+  }
+
+  onFileParsingData(data) {
+  }
+ 
+  onWebsocketAttached(data) {
+    this.wfs.trigger(Event.BUFFER_APPENDING, {type: 'video', data: data.payload, parent : 'main'}); 
+  }
+  
+  onFragParsingInitSegment(data) {
+  	 var tracks = data.tracks, trackName, track;
+ 
+      track = tracks.video;
+      if(track) { 
+        track.id = data.id;
+      }
+ 
+      for (trackName in tracks) {
+        track = tracks[trackName];
+        var initSegment = track.initSegment;
+        if (initSegment) {
+          this.pendingAppending++;
+          this.wfs.trigger(Event.BUFFER_APPENDING, {type: trackName, data: initSegment, parent : 'main'});
+        }
+      }
+ 
+  }
+
+  onFragParsingData(data) {
+ 
+      if(data.type === 'video') {
+     
+      }
+       
+      [data.data1, data.data2].forEach(buffer => {
+        if (buffer) {
+          this.pendingAppending++;
+          this.wfs.trigger(Event.BUFFER_APPENDING, {type: data.type, data: buffer, parent : 'main'}); 
+        }
+      });
+ 
+  }
+
+}
+export default FlowController;  

+ 294 - 0
static/src/demux/exp-golomb.js

@@ -0,0 +1,294 @@
+/**
+ * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
+*/
+
+import {logger} from '../utils/logger';
+
+class ExpGolomb {
+
+  constructor(data) {
+    this.data = data;
+    // the number of bytes left to examine in this.data
+    this.bytesAvailable = this.data.byteLength;
+    // the current word being examined
+    this.word = 0; // :uint
+    // the number of bits left to examine in the current word
+    this.bitsAvailable = 0; // :uint
+  }
+
+  // ():void
+  loadWord() {
+    var
+      position = this.data.byteLength - this.bytesAvailable,
+      workingBytes = new Uint8Array(4),
+      availableBytes = Math.min(4, this.bytesAvailable);
+    if (availableBytes === 0) {
+      throw new Error('no bytes available');
+    }
+    workingBytes.set(this.data.subarray(position, position + availableBytes));
+    this.word = new DataView(workingBytes.buffer).getUint32(0);
+    // track the amount of this.data that has been processed
+    this.bitsAvailable = availableBytes * 8;
+    this.bytesAvailable -= availableBytes;
+  }
+
+  // (count:int):void
+  skipBits(count) {
+    var skipBytes; // :int
+    if (this.bitsAvailable > count) {
+      this.word <<= count;
+      this.bitsAvailable -= count;
+    } else {
+      count -= this.bitsAvailable;
+      skipBytes = count >> 3;
+      count -= (skipBytes >> 3);
+      this.bytesAvailable -= skipBytes;
+      this.loadWord();
+      this.word <<= count;
+      this.bitsAvailable -= count;
+    }
+  }
+
+  // (size:int):uint
+  readBits(size) {
+    var
+      bits = Math.min(this.bitsAvailable, size), // :uint
+      valu = this.word >>> (32 - bits); // :uint
+    if (size > 32) {
+      logger.error('Cannot read more than 32 bits at a time');
+    }
+    this.bitsAvailable -= bits;
+    if (this.bitsAvailable > 0) {
+      this.word <<= bits;
+    } else if (this.bytesAvailable > 0) {
+      this.loadWord();
+    }
+    bits = size - bits;
+    if (bits > 0) {
+      return valu << bits | this.readBits(bits);
+    } else {
+      return valu;
+    }
+  }
+
+  // ():uint
+  skipLZ() {
+    var leadingZeroCount; // :uint
+    for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) {
+      if (0 !== (this.word & (0x80000000 >>> leadingZeroCount))) {
+        // the first bit of working word is 1
+        this.word <<= leadingZeroCount;
+        this.bitsAvailable -= leadingZeroCount;
+        return leadingZeroCount;
+      }
+    }
+    // we exhausted word and still have not found a 1
+    this.loadWord();
+    return leadingZeroCount + this.skipLZ();
+  }
+
+  // ():void
+  skipUEG() {
+    this.skipBits(1 + this.skipLZ());
+  }
+
+  // ():void
+  skipEG() {
+    this.skipBits(1 + this.skipLZ());
+  }
+
+  // ():uint
+  readUEG() {
+    var clz = this.skipLZ(); // :uint
+    return this.readBits(clz + 1) - 1;
+  }
+
+  // ():int
+  readEG() {
+    var valu = this.readUEG(); // :int
+    if (0x01 & valu) {
+      // the number is odd if the low order bit is set
+      return (1 + valu) >>> 1; // add 1 to make it even, and divide by 2
+    } else {
+      return -1 * (valu >>> 1); // divide by two then make it negative
+    }
+  }
+
+  // Some convenience functions
+  // :Boolean
+  readBoolean() {
+    return 1 === this.readBits(1);
+  }
+
+  // ():int
+  readUByte() {
+    return this.readBits(8);
+  }
+
+  // ():int
+  readUShort() {
+    return this.readBits(16);
+  }
+    // ():int
+  readUInt() {
+    return this.readBits(32);
+  }
+
+  /**
+   * Advance the ExpGolomb decoder past a scaling list. The scaling
+   * list is optionally transmitted as part of a sequence parameter
+   * set and is not relevant to transmuxing.
+   * @param count {number} the number of entries in this scaling list
+   * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
+   */
+  skipScalingList(count) {
+    var
+      lastScale = 8,
+      nextScale = 8,
+      j,
+      deltaScale;
+    for (j = 0; j < count; j++) {
+      if (nextScale !== 0) {
+        deltaScale = this.readEG();
+        nextScale = (lastScale + deltaScale + 256) % 256;
+      }
+      lastScale = (nextScale === 0) ? lastScale : nextScale;
+    }
+  }
+
+  /**
+   * Read a sequence parameter set and return some interesting video
+   * properties. A sequence parameter set is the H264 metadata that
+   * describes the properties of upcoming video frames.
+   * @param data {Uint8Array} the bytes of a sequence parameter set
+   * @return {object} an object with configuration parsed from the
+   * sequence parameter set, including the dimensions of the
+   * associated video frames.
+   */
+  readSPS() {
+    var
+      frameCropLeftOffset = 0,
+      frameCropRightOffset = 0,
+      frameCropTopOffset = 0,
+      frameCropBottomOffset = 0,
+      sarScale = 1,
+      profileIdc,profileCompat,levelIdc,
+      numRefFramesInPicOrderCntCycle, picWidthInMbsMinus1,
+      picHeightInMapUnitsMinus1,
+      frameMbsOnlyFlag,
+      scalingListCount,
+      i;
+    this.readUByte();
+    profileIdc = this.readUByte(); // profile_idc
+    profileCompat = this.readBits(5); // constraint_set[0-4]_flag, u(5)
+    this.skipBits(3); // reserved_zero_3bits u(3),
+    levelIdc = this.readUByte(); //level_idc u(8)
+    this.skipUEG(); // seq_parameter_set_id
+    // some profiles have more optional data we don't need
+    if (profileIdc === 100 ||
+        profileIdc === 110 ||
+        profileIdc === 122 ||
+        profileIdc === 244 ||
+        profileIdc === 44  ||
+        profileIdc === 83  ||
+        profileIdc === 86  ||
+        profileIdc === 118 ||
+        profileIdc === 128) {
+      var chromaFormatIdc = this.readUEG();
+      if (chromaFormatIdc === 3) {
+        this.skipBits(1); // separate_colour_plane_flag
+      }
+      this.skipUEG(); // bit_depth_luma_minus8
+      this.skipUEG(); // bit_depth_chroma_minus8
+      this.skipBits(1); // qpprime_y_zero_transform_bypass_flag
+      if (this.readBoolean()) { // seq_scaling_matrix_present_flag
+        scalingListCount = (chromaFormatIdc !== 3) ? 8 : 12;
+        for (i = 0; i < scalingListCount; i++) {
+          if (this.readBoolean()) { // seq_scaling_list_present_flag[ i ]
+            if (i < 6) {
+              this.skipScalingList(16);
+            } else {
+              this.skipScalingList(64);
+            }
+          }
+        }
+      }
+    }
+    this.skipUEG(); // log2_max_frame_num_minus4
+    var picOrderCntType = this.readUEG();
+    if (picOrderCntType === 0) {
+      this.readUEG(); //log2_max_pic_order_cnt_lsb_minus4
+    } else if (picOrderCntType === 1) {
+      this.skipBits(1); // delta_pic_order_always_zero_flag
+      this.skipEG(); // offset_for_non_ref_pic
+      this.skipEG(); // offset_for_top_to_bottom_field
+      numRefFramesInPicOrderCntCycle = this.readUEG();
+      for(i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
+        this.skipEG(); // offset_for_ref_frame[ i ]
+      }
+    }
+    this.skipUEG(); // max_num_ref_frames
+    this.skipBits(1); // gaps_in_frame_num_value_allowed_flag
+    picWidthInMbsMinus1 = this.readUEG();
+    picHeightInMapUnitsMinus1 = this.readUEG();
+    frameMbsOnlyFlag = this.readBits(1);
+    if (frameMbsOnlyFlag === 0) {
+      this.skipBits(1); // mb_adaptive_frame_field_flag
+    }
+    this.skipBits(1); // direct_8x8_inference_flag
+    if (this.readBoolean()) { // frame_cropping_flag
+      frameCropLeftOffset = this.readUEG();
+      frameCropRightOffset = this.readUEG();
+      frameCropTopOffset = this.readUEG();
+      frameCropBottomOffset = this.readUEG();
+    }
+    if (this.readBoolean()) {
+      // vui_parameters_present_flag
+      if (this.readBoolean()) {
+        // aspect_ratio_info_present_flag
+        let sarRatio;
+        const aspectRatioIdc = this.readUByte();
+        switch (aspectRatioIdc) {
+          case 1: sarRatio = [1,1]; break;
+          case 2: sarRatio = [12,11]; break;
+          case 3: sarRatio = [10,11]; break;
+          case 4: sarRatio = [16,11]; break;
+          case 5: sarRatio = [40,33]; break;
+          case 6: sarRatio = [24,11]; break;
+          case 7: sarRatio = [20,11]; break;
+          case 8: sarRatio = [32,11]; break;
+          case 9: sarRatio = [80,33]; break;
+          case 10: sarRatio = [18,11]; break;
+          case 11: sarRatio = [15,11]; break;
+          case 12: sarRatio = [64,33]; break;
+          case 13: sarRatio = [160,99]; break;
+          case 14: sarRatio = [4,3]; break;
+          case 15: sarRatio = [3,2]; break;
+          case 16: sarRatio = [2,1]; break;
+          case 255: {
+            sarRatio = [this.readUByte() << 8 | this.readUByte(), this.readUByte() << 8 | this.readUByte()];
+            break;
+          }
+        }
+        if (sarRatio) {
+          sarScale = sarRatio[0] / sarRatio[1];
+        }
+      }
+    }
+    return {
+      width: Math.ceil((((picWidthInMbsMinus1 + 1) * 16) - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale),
+      height: ((2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16) - ((frameMbsOnlyFlag? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset))
+    };
+  }
+
+  readSliceType() {
+    // skip NALu type
+    this.readUByte();
+    // discard first_mb_in_slice
+    this.readUEG();
+    // return slice_type
+    return this.readUEG();
+  }
+}
+
+export default ExpGolomb;

+ 277 - 0
static/src/demux/h264-demuxer.js

@@ -0,0 +1,277 @@
+/**
+
+*/
+import {ErrorTypes, ErrorDetails} from '../errors';
+import Event from '../events';
+import ExpGolomb from './exp-golomb';
+import EventHandler from '../event-handler';
+import MP4Remuxer from '../remux/mp4-remuxer';
+
+class h264Demuxer extends EventHandler {
+  
+  constructor(wfs, config=null) {
+    super(wfs, 
+      Event.H264_DATA_PARSING);
+
+    this.config = this.wfs.config || config;
+    this.wfs = wfs;
+    this.id = 'main';
+    var typeSupported = {
+      mp4 : MediaSource.isTypeSupported('video/mp4')//,
+     // mp2t : wfs.config.enableMP2TPassThrough && MediaSource.isTypeSupported('video/mp2t')
+    };
+ 
+    this.remuxer = new MP4Remuxer(this.wfs, this.id , this.config);   
+    this.contiguous = true; 
+    this.timeOffset = 1;
+    this.sn = 0;
+    this.TIMESCALE = 90000; 
+    this.timestamp = 0;
+    this.scaleFactor = this.TIMESCALE /1000;
+    this.H264_TIMEBASE = 3000;
+    this._avcTrack = {container : 'video/mp4', type: 'video', id :1, sequenceNumber: 0,
+    //this._avcTrack = {container : 'video/mp4', type: 'video', id :1, sequenceNumber: 0,
+     samples : [], len : 0, nbNalu : 0, dropped : 0, count : 0 };
+    this.browserType = 0;
+    if (navigator.userAgent.toLowerCase().indexOf('firefox') !== -1){
+      this.browserType = 1;
+    }
+  }
+
+  destroy() {
+    EventHandler.prototype.destroy.call(this);
+  }
+ 
+  getTimestampM() {
+    this.timestamp += this.H264_TIMEBASE;
+    return  this.timestamp;
+  }
+
+  onH264DataParsing(event){ 
+    this._parseAVCTrack( event.data); 
+    if (this.browserType === 1){ // Firefox
+      this.remuxer.pushVideo(0, this.sn, this._avcTrack, this.timeOffset, this.contiguous);
+      this.sn += 1;
+    }else{
+        this.remuxer.pushVideo(0, this.sn, this._avcTrack, this.timeOffset, this.contiguous);
+        this.sn += 1;
+    } 
+  } 
+
+  _parseAVCTrack(array) {
+    var track = this._avcTrack,
+      samples = track.samples,
+      units = this._parseAVCNALu(array),
+      units2 = [],
+      debug = false,
+      key = false,
+      length = 0,
+      expGolombDecoder,
+      avcSample,
+      push,
+      i;    
+    var debugString = '';
+    var pushAccesUnit = function() {
+      if (units2.length) { 
+        if (!this.config.forceKeyFrameOnDiscontinuity ||
+            key === true ||
+            (track.sps && (samples.length || this.contiguous))) { 
+          var tss = this.getTimestampM();
+          avcSample = {units: { units : units2, length : length}, pts: tss, dts: tss, key: key};
+          samples.push(avcSample);
+          track.len += length;
+          track.nbNalu += units2.length;
+        } else { 
+          track.dropped++;
+        }
+        units2 = [];
+        length = 0;
+      }
+    }.bind(this);
+
+    units.forEach(unit => {
+      switch(unit.type) {
+        //NDR
+         case 1:
+           push = true;
+           if(debug) {
+            debugString += 'NDR ';
+           }
+           break;
+        //IDR
+        case 5:
+          push = true;
+          if(debug) {
+            debugString += 'IDR ';
+          } 
+          key = true;
+          break;
+        //SEI
+        case 6:
+          unit.data = this.discardEPB(unit.data);
+          expGolombDecoder = new ExpGolomb(unit.data);
+          // skip frameType
+          expGolombDecoder.readUByte();
+          break;
+        //SPS
+        case 7:
+          push = false;
+          if(debug) {
+            debugString += 'SPS ';
+          }
+          if(!track.sps) {
+            expGolombDecoder = new ExpGolomb(unit.data);
+            var config = expGolombDecoder.readSPS();
+            track.width = config.width;
+            track.height = config.height;
+            track.sps = [unit.data];
+            track.duration = 0; 
+            var codecarray = unit.data.subarray(1, 4);
+            var codecstring = 'avc1.';
+            for (i = 0; i < 3; i++) {
+              var h = codecarray[i].toString(16);
+              if (h.length < 2) {
+                h = '0' + h;
+              }
+              codecstring += h;
+            }
+            track.codec = codecstring;         
+            this.wfs.trigger(Event.BUFFER_RESET, {  mimeType:  track.codec } ); 
+            push = true;
+          }
+          break;
+        //PPS
+        case 8:
+          push = false;
+          if(debug) {
+            debugString += 'PPS ';
+          }
+          if (!track.pps) {
+            track.pps = [unit.data];
+             push = true;
+          }
+          break; 
+        case 9:
+          push = false;
+          if(debug) {
+            debugString += 'AUD ';
+          }
+          pushAccesUnit();
+          break;      
+        default:
+          push = false;
+          debugString += 'unknown NAL ' + unit.type + ' ';
+          break;
+      }
+    
+      if(push) {
+        units2.push(unit);
+        length+=unit.data.byteLength; 
+      }
+    
+    });
+    
+    if(debug || debugString.length) {
+      logger.log(debugString);
+    }
+    
+    pushAccesUnit();
+   
+  }
+  
+  _parseAVCNALu(array) {
+    var i = 0, len = array.byteLength, value, overflow, state = 0; //state = this.avcNaluState;
+    var units = [], unit, unitType, lastUnitStart, lastUnitType; 
+    while (i < len) {
+      value = array[i++];
+      // finding 3 or 4-byte start codes (00 00 01 OR 00 00 00 01)
+      switch (state) {
+        case 0:
+          if (value === 0) {
+            state = 1;
+          }
+          break;
+        case 1:
+          if( value === 0) {
+            state = 2;
+          } else {
+            state = 0;
+          }
+          break;
+        case 2:
+        case 3:
+          if( value === 0) {
+            state = 3;
+          } else if (value === 1 && i < len) {
+            unitType = array[i] & 0x1f;
+            if (lastUnitStart) {
+              unit = {data: array.subarray(lastUnitStart, i - state - 1), type: lastUnitType}; 
+              units.push(unit); 
+            } else { 
+            }
+            lastUnitStart = i;
+            lastUnitType = unitType;
+            state = 0;
+          } else {
+            state = 0;
+          }
+          break;
+        default:
+          break;
+      }
+    }
+
+    if (lastUnitStart) { 
+      unit = {data: array.subarray(lastUnitStart, len), type: lastUnitType, state : state};
+      units.push(unit); 
+    }
+
+    return units;
+  }
+
+  /**
+   * remove Emulation Prevention bytes from a RBSP
+   */
+  discardEPB(data) {
+    var length = data.byteLength,
+        EPBPositions = [],
+        i = 1,
+        newLength, newData;
+    // Find all `Emulation Prevention Bytes`
+    while (i < length - 2) {
+      if (data[i] === 0 &&
+          data[i + 1] === 0 &&
+          data[i + 2] === 0x03) {
+        EPBPositions.push(i + 2);
+        i += 2;
+      } else {
+        i++;
+      }
+    }
+    // If no Emulation Prevention Bytes were found just return the original
+    // array
+    if (EPBPositions.length === 0) {
+      return data;
+    }
+    // Create a new array to hold the NAL unit data
+    newLength = length - EPBPositions.length;
+    newData = new Uint8Array(newLength);
+    var sourceIndex = 0;
+
+    for (i = 0; i < newLength; sourceIndex++, i++) {
+      if (sourceIndex === EPBPositions[0]) {
+        // Skip this byte
+        sourceIndex++;
+        // Remove this position index
+        EPBPositions.shift();
+      }
+      newData[i] = data[sourceIndex];
+    }
+    return newData;
+  }
+
+ 
+}
+
+export default h264Demuxer;
+

+ 57 - 0
static/src/errors.js

@@ -0,0 +1,57 @@
+export const ErrorTypes = {
+  // Identifier for a network error (loading error / timeout ...)
+  NETWORK_ERROR: 'networkError',
+  // Identifier for a media Error (video/parsing/mediasource error)
+  MEDIA_ERROR: 'mediaError',
+  // Identifier for all other errors
+  OTHER_ERROR: 'otherError'
+};
+
+export const ErrorDetails = {
+  // Identifier for a manifest load error - data: { url : faulty URL, response : { code: error code, text: error text }}
+  MANIFEST_LOAD_ERROR: 'manifestLoadError',
+  // Identifier for a manifest load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
+  MANIFEST_LOAD_TIMEOUT: 'manifestLoadTimeOut',
+  // Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason}
+  MANIFEST_PARSING_ERROR: 'manifestParsingError',
+  // Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason}
+  MANIFEST_INCOMPATIBLE_CODECS_ERROR: 'manifestIncompatibleCodecsError',
+  // Identifier for a level load error - data: { url : faulty URL, response : { code: error code, text: error text }}
+  LEVEL_LOAD_ERROR: 'levelLoadError',
+  // Identifier for a level load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
+  LEVEL_LOAD_TIMEOUT: 'levelLoadTimeOut',
+  // Identifier for a level switch error - data: { level : faulty level Id, event : error description}
+  LEVEL_SWITCH_ERROR: 'levelSwitchError',
+  // Identifier for an audio track load error - data: { url : faulty URL, response : { code: error code, text: error text }}
+  AUDIO_TRACK_LOAD_ERROR: 'audioTrackLoadError',
+  // Identifier for an audio track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}
+  AUDIO_TRACK_LOAD_TIMEOUT: 'audioTrackLoadTimeOut',
+  // Identifier for fragment load error - data: { frag : fragment object, response : { code: error code, text: error text }}
+  FRAG_LOAD_ERROR: 'fragLoadError',
+  // Identifier for fragment loop loading error - data: { frag : fragment object}
+  FRAG_LOOP_LOADING_ERROR: 'fragLoopLoadingError',
+  // Identifier for fragment load timeout error - data: { frag : fragment object}
+  FRAG_LOAD_TIMEOUT: 'fragLoadTimeOut',
+  // Identifier for a fragment decryption error event - data: parsing error description
+  FRAG_DECRYPT_ERROR: 'fragDecryptError',
+  // Identifier for a fragment parsing error event - data: parsing error description
+  FRAG_PARSING_ERROR: 'fragParsingError',
+  // Identifier for decrypt key load error - data: { frag : fragment object, response : { code: error code, text: error text }}
+  KEY_LOAD_ERROR: 'keyLoadError',
+  // Identifier for decrypt key load timeout error - data: { frag : fragment object}
+  KEY_LOAD_TIMEOUT: 'keyLoadTimeOut',
+  // Triggered when an exception occurs while adding a sourceBuffer to MediaSource - data : {  err : exception , mimeType : mimeType }
+  BUFFER_ADD_CODEC_ERROR: 'bufferAddCodecError',
+  // Identifier for a buffer append error - data: append error description
+  BUFFER_APPEND_ERROR: 'bufferAppendError',
+  // Identifier for a buffer appending error event - data: appending error description
+  BUFFER_APPENDING_ERROR: 'bufferAppendingError',
+  // Identifier for a buffer stalled error event
+  BUFFER_STALLED_ERROR: 'bufferStalledError',
+  // Identifier for a buffer full event
+  BUFFER_FULL_ERROR: 'bufferFullError',
+  // Identifier for a buffer seek over hole event
+  BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole',
+  // Identifier for an internal exception happening inside hls.js while handling an event
+  INTERNAL_EXCEPTION: 'internalException'
+};

+ 70 - 0
static/src/event-handler.js

@@ -0,0 +1,70 @@
+/*
+*
+* All objects in the event handling chain should inherit from this class
+*
+*/ 
+import Event from './events';
+
+class EventHandler {
+
+  constructor(wfs, ...events) {
+    this.wfs = wfs;
+    this.onEvent = this.onEvent.bind(this);
+    this.handledEvents = events;
+    this.useGenericHandler = true;
+
+    this.registerListeners();
+  }
+
+  destroy() {
+    this.unregisterListeners();
+  }
+
+  isEventHandler() {
+    return typeof this.handledEvents === 'object' && this.handledEvents.length && typeof this.onEvent === 'function';
+  }
+
+  registerListeners() {
+    if (this.isEventHandler()) {
+      this.handledEvents.forEach(function(event) {
+        if (event === 'wfsEventGeneric') {
+          //throw new Error('Forbidden event name: ' + event);
+        }
+        this.wfs.on(event, this.onEvent);
+      }.bind(this));
+    }
+  }
+
+  unregisterListeners() {
+    if (this.isEventHandler()) {
+      this.handledEvents.forEach(function(event) {
+        this.wfs.off(event, this.onEvent);
+      }.bind(this));
+    }
+  }
+
+  /**
+   * arguments: event (string), data (any)
+   */
+  onEvent(event, data) {
+    this.onEventGeneric(event, data);
+  }
+
+  onEventGeneric(event, data) {
+    var eventToFunction = function(event, data) {
+      var funcName = 'on' + event.replace('wfs', '');
+      if (typeof this[funcName] !== 'function') {
+        //throw new Error(`Event ${event} has no generic handler in this ${this.constructor.name} class (tried ${funcName})`);
+      }
+      return this[funcName].bind(this, data);
+    };
+    try {
+      eventToFunction.call(this, event, data).call();
+    } catch (err) {
+      console.log(`internal error happened while processing ${event}:${err.message}`);
+   //   this.hls.trigger(Event.ERROR, {type: ErrorTypes.OTHER_ERROR, details: ErrorDetails.INTERNAL_EXCEPTION, fatal: false, event : event, err : err});
+    }
+  }
+}
+
+export default EventHandler;

+ 40 - 0
static/src/events.js

@@ -0,0 +1,40 @@
+module.exports = {
+ 
+  MEDIA_ATTACHING: 'wfsMediaAttaching',  
+ 
+  MEDIA_ATTACHED: 'wfsMediaAttached',
+ 
+  FRAG_LOADING: 'wfsFragLoading',
+
+  BUFFER_CREATED: 'wfsBufferCreated', 
+
+  BUFFER_APPENDING: 'wfsBufferAppending',
+
+  BUFFER_RESET: 'wfsBufferReset', 
+
+  FRAG_PARSING_DATA: 'wfsFragParsingData',
+ 
+  FRAG_PARSING_INIT_SEGMENT: 'wfsFragParsingInitSegment',
+//------------------------------------------
+  H264_DATA_PARSING: 'wfsH264DataParsing',
+//------------------------------------------
+  WEBSOCKET_ATTACHED: 'wfsWebsocketAttached',
+
+  WEBSOCKET_ATTACHING: 'wfsWebsocketAttaching',
+
+  WEBSOCKET_DATA_UPLOADING: 'wfsWebsocketDataUploading',
+
+  WEBSOCKET_MESSAGE_SENDING: 'wfsWebsocketMessageSending',   
+//------------------------------------------
+  FILE_HEAD_LOADING: 'wfsFileHeadLoading',
+
+  FILE_HEAD_LOADED: 'wfsFileHeadLoaded',
+
+  FILE_DATA_LOADING: 'wfsFileDataLoading',
+
+  FILE_DATA_LOADED: 'wfsFileDataLoaded',
+
+  FILE_PARSING_DATA: 'wfsFileParsingData'
+//------------------------------------------
+
+};

+ 0 - 0
static/src/helper/aac.js


Some files were not shown because too many files changed in this diff