Commit 11a60adb533eaed6087324e4f7ebd03a22b8a1d1
0 parents
Init
Showing
78 changed files
with
8239 additions
and
2 deletions
.gitignore
0 → 100644
LICENSE
0 → 100644
| 1 | +++ a/LICENSE | |
| 1 | +Copyright [2019] [matrixy] | |
| 2 | + | |
| 3 | +Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 | +you may not use this file except in compliance with the License. | |
| 5 | +You may obtain a copy of the License at | |
| 6 | + | |
| 7 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 | + | |
| 9 | +Unless required by applicable law or agreed to in writing, software | |
| 10 | +distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 | +See the License for the specific language governing permissions and | |
| 13 | +limitations under the License. | |
| 0 | 14 | \ No newline at end of file | ... | ... |
README.md
0 → 100644
| 1 | +++ a/README.md | |
| 1 | +## 目录 | |
| 2 | +<ol> | |
| 3 | + <li><a href="#jtt1078-video-server">简介说明</a></li> | |
| 4 | + <li><a href="#分支说明">分支说明</a></li> | |
| 5 | + <li><a href="#项目说明">项目说明</a></li> | |
| 6 | + <li><a href="#准备工具">准备工具</a></li> | |
| 7 | + <li><a href="#测试步骤">测试步骤</a></li> | |
| 8 | + <li><a href="#测试环境">测试环境</a></li> | |
| 9 | + <li><a href="#TODO">TODO</a></li> | |
| 10 | + <li><a href="#致谢">致谢</a></li> | |
| 11 | + <li><a href="#推荐群友项目">推荐群友项目</a></li> | |
| 12 | + <li><a href="#交流讨论">交流讨论</a></li> | |
| 13 | +</ol> | |
| 14 | + | |
| 15 | +<div align="center"><img src="./doc/1078.png" /></div> | |
| 16 | + | |
| 17 | +<hr /> | |
| 18 | + | |
| 19 | +## jtt1078-video-server | |
| 20 | +基于JT/T 1078协议实现的视频转播服务器,当车机服务器端主动下发**音视频实时传输控制**消息(0x9101)后,车载终端连接到此服务器后,发送指定摄像头所采集的视频流,此项目服务器完成音视频数据接收并转码,完成转播的流程,提供各平台的播放支撑。 | |
| 21 | + | |
| 22 | +同时,本项目在配置 **ffmpeg路径** 及 **rtmp url** 后,将同时输出一路到 **RTMP** 服务器上去,为移动端播放提供音视频支持(注意,由于旁路的RTMP流是通过ffmpeg子进程实现,并且有音频转码的过程,所以性能将有很大的下降)。 | |
| 23 | + | |
| 24 | +> 非常感谢 **孤峰赏月/hx([github/jelycom](https://github.com/jelycom))** 提供的mp3音频支持。 | |
| 25 | + | |
| 26 | +## 分支说明 | |
| 27 | +原项目有4个分支不同的实现方式,现将其它分支全部删除,已经用不上了。 | |
| 28 | +配置了ffmpeg和rtmp,可以想办法同时输出到比如HLS等。 | |
| 29 | + | |
| 30 | +> 有其它语言的开发者,可以参考我的“[JTT/1078音视频传输协议开发指南](https://www.hentai.org.cn/article?id=8)”,我所知道的官方文档里的错误或是缺陷以及坑,我全部写了下来,希望对你有帮助。 | |
| 31 | + | |
| 32 | +### 项目说明 | |
| 33 | +本项目接收来自于车载终端发过来的音视频数据,视频直接封装为FLV TAG,音频完成G.711A、G.711U、ADPCMA、G726到PCM的转码,并使用MP3压缩后再封装为FLV TAG。 | |
| 34 | + | |
| 35 | +#### 视频编码支持 | |
| 36 | +目前几乎所有的终端视频,默认的视频编码都是h264,打包成flv也是非常简单的,有个别厂家使用avs,但是我没有碰到过。本项目目前也只支持h264编码的视频。 | |
| 37 | + | |
| 38 | +#### 音频编码支持 | |
| 39 | +|音频编码|支持|备注| | |
| 40 | +|---|---|---| | |
| 41 | +|G.711A|Y|支持| | |
| 42 | +|G.711U|Y|支持| | |
| 43 | +|ADPCMA|Y|支持| | |
| 44 | +|G.726|Y|支持| | |
| 45 | + | |
| 46 | +音频编码太多,也没那么多设备可以测试的,比较常见的就G.711A和ADPCMA这两种,本程序对于不支持的音频,将作 **静音处理** 。 | |
| 47 | + | |
| 48 | +#### 音频编码转码扩展实现 | |
| 49 | +继承并实现`AudioCodec`类的抽象方法,完成任意音频到PCM编码的转码过程,并且补充`AudioCodec.getCodec()`工厂方法即可。`AudioCodec`抽象类原型如下: | |
| 50 | +```java | |
| 51 | +public abstract class AudioCodec | |
| 52 | +{ | |
| 53 | + // 转换至PCM | |
| 54 | + public abstract byte[] toPCM(byte[] data); | |
| 55 | + // 由PCM转为当前编码,可以留空,反正又没有调用 | |
| 56 | + public abstract byte[] fromPCM(byte[] data); | |
| 57 | +} | |
| 58 | +``` | |
| 59 | + | |
| 60 | +### 准备工具 | |
| 61 | +项目里准备了一个测试程序(`src/main/java/cn.org.hentai.jtt1078.test.VideoPushTest.java`),以及一个数据文件(`src/main/resources/tcpdump.bin`),数据文件是通过工具采集的一段几分钟时长的车载终端发送上来的原始消息包,测试程序可以持续不断的、慢慢的发送数据文件里的内容,用来模拟车载终端发送视频流的过程。 | |
| 62 | + | |
| 63 | +另外,新增了 `cn.org.hentai.jtt1078.test.RTPGenerate` 类,用于读取bin文件,并且修改SIM卡号和通道号,创建大量数据文件以便于压力测试。 | |
| 64 | + | |
| 65 | +### 测试步骤 | |
| 66 | +1. 配置好服务器端,修改`app.properties`里的配置项。 | |
| 67 | +2. 直接在IDE里运行`cn.org.hentai.jtt1078.app.VideoServerApp`,或对项目进行打包,执行`mvn package`,执行`java -jar jtt1078-video-server-1.0-SNAPSHOT.jar`来启动服务器端。 | |
| 68 | +3. 运行`VideoPushTest.java`,开始模拟车载终端的视频推送。 | |
| 69 | +4. 开始后,控制台里会输出显示**start publishing: 013800138999-2**的字样 | |
| 70 | +5. 打开浏览器,输入 **http://localhost:3333/test/multimedia#013800138999-2** 后回车 | |
| 71 | +6. 点击网页上的**play video**,开始播放视频 | |
| 72 | + | |
| 73 | +### 测试环境 | |
| 74 | +我在我自己的VPS上搭建了一个1078音视频环境,完全使用了**flv**分支上的代码来创建,各位可以让终端将音视频发送到此服务器或是使用**netcat**等网络工具发送模拟数据来仿真终端,来体验音视频的效果。下面我们说一下通过**netcat**来模拟终端的方法: | |
| 75 | + | |
| 76 | +|标题|说明| | |
| 77 | +|---|---| | |
| 78 | +|1078音视频服务器|185.251.248.4:10780| | |
| 79 | +|实时音视频播放页面|http://1078.hentai.org.cn/test/multimedia#SIM-CHANNEL| | |
| 80 | + | |
| 81 | +1. 首先,本项目的 **/src/main/resources/** 下的 **tcpdump.bin** 即为我抓包存下来的终端音视频数据文件,通过`cat tcpdump.bin | pv -L 40k -q | nc 185.251.248.4 10780`即可以每秒40kBPS的速度,向服务器端持续的发送数据。 | |
| 82 | +2. 在浏览器里打开**http://1078.hentai.org.cn/test/multimedia#SIM-CHANNEL** (注意替换掉后面的SIM和CHANNEL,即终端的SIM卡号,不足12位前面补0,CHANNEL即为通道号),然后点击网页上的**play video**即可。 | |
| 83 | + | |
| 84 | +> 由于我的服务器IP随时可能会发生变化,建设在尝试连接测试服务器前,先通过`ping www.hentai.org.cn`来确定最新的IP。 | |
| 85 | + | |
| 86 | +### 项目文件说明 | |
| 87 | +``` | |
| 88 | + | |
| 89 | + | |
| 90 | +├── doc | |
| 91 | +│ ├── 1078.png(图标) | |
| 92 | +│ └── ffmpeg.png | |
| 93 | +├── LICENSE(开源协议) | |
| 94 | +├── pom.xml | |
| 95 | +├── README.md(项目说明) | |
| 96 | +├── src | |
| 97 | +│ └── main | |
| 98 | +│ ├── java | |
| 99 | +│ │ └── cn | |
| 100 | +│ │ └── org | |
| 101 | +│ │ └── hentai | |
| 102 | +│ │ └── jtt1078 | |
| 103 | +│ │ ├── app | |
| 104 | +│ │ │ └── VideoServerApp.java(主入口程序) | |
| 105 | +│ │ ├── codec | |
| 106 | +│ │ │ ├── ADPCMCodec.java(ADPCM编解码器) | |
| 107 | +│ │ │ ├── AudioCodec.java(音频编解码抽象父类) | |
| 108 | +│ │ │ ├── G711Codec.java(G711A/alaw编解码器) | |
| 109 | +│ │ │ ├── G711UCodec.java(G711U/ulaw编解码器) | |
| 110 | +│ │ │ ├── g726(G726编解码实现) | |
| 111 | +│ │ │ │ ├── G726_16.java | |
| 112 | +│ │ │ │ ├── G726_24.java | |
| 113 | +│ │ │ │ ├── G726_32.java | |
| 114 | +│ │ │ │ ├── G726_40.java | |
| 115 | +│ │ │ │ ├── G726.java | |
| 116 | +│ │ │ │ └── G726State.java | |
| 117 | +│ │ │ ├── G726Codec.java(G726编解码器) | |
| 118 | +│ │ │ ├── MP3Encoder.java(PCM到MP3压缩编码器) | |
| 119 | +│ │ │ └── SilenceCodec.java(静音化解码器) | |
| 120 | +│ │ ├── entity | |
| 121 | +│ │ │ ├── Audio.java | |
| 122 | +│ │ │ ├── MediaEncoding.java | |
| 123 | +│ │ │ ├── Media.java | |
| 124 | +│ │ │ └── Video.java | |
| 125 | +│ │ ├── flv | |
| 126 | +│ │ │ ├── AudioTag.java | |
| 127 | +│ │ │ ├── FlvAudioTagEncoder.java | |
| 128 | +│ │ │ ├── FlvEncoder.java(H264到FLV封装编码器) | |
| 129 | +│ │ │ └── FlvTag.java | |
| 130 | +│ │ ├── http(内置HTTP服务,提供HTTP-CHUNKED传输支持) | |
| 131 | +│ │ │ ├── GeneralResponseWriter.java | |
| 132 | +│ │ │ └── NettyHttpServerHandler.java | |
| 133 | +│ │ ├── publisher | |
| 134 | +│ │ │ ├── Channel.java(一个通道一个Channel实例,Subscriber订阅Channel上的音频与视频) | |
| 135 | +│ │ │ └── PublishManager.java(管理Channel和Subscriber) | |
| 136 | +│ │ ├── server(负责完成1078 RTP消息包的接收和解码) | |
| 137 | +│ │ │ ├── Jtt1078Decoder.java | |
| 138 | +│ │ │ ├── Jtt1078Handler.java | |
| 139 | +│ │ │ ├── Jtt1078MessageDecoder.java | |
| 140 | +│ │ │ └── Session.java | |
| 141 | +│ │ ├── subscriber | |
| 142 | +│ │ │ ├── RTMPPublisher.java(通过ffmpeg子进程将http-flv另外传输一份到RTMP服务器的实现) | |
| 143 | +│ │ │ ├── Subscriber.java(订阅者抽象类定义) | |
| 144 | +│ │ │ └── VideoSubscriber.java(视频订阅者) | |
| 145 | +│ │ ├── test(测试代码) | |
| 146 | +│ │ │ ├── AudioTest.java | |
| 147 | +│ │ │ ├── ChannelTest.java | |
| 148 | +│ │ │ ├── FuckTest.java | |
| 149 | +│ │ │ ├── G711ATest.java | |
| 150 | +│ │ │ ├── MP3Test.java | |
| 151 | +│ │ │ ├── RTPGenerate.java(通过读取原始消息数据文件,创建N个修改了sim卡号的新数据文件,可用于压力测试) | |
| 152 | +│ │ │ ├── VideoPushTest.java | |
| 153 | +│ │ │ ├── VideoServer.java | |
| 154 | +│ │ │ └── WAVTest.java | |
| 155 | +│ │ └── util | |
| 156 | +│ │ ├── ByteBufUtils.java | |
| 157 | +│ │ ├── ByteHolder.java | |
| 158 | +│ │ ├── ByteUtils.java | |
| 159 | +│ │ ├── Configs.java | |
| 160 | +│ │ ├── FileUtils.java | |
| 161 | +│ │ ├── FLVUtils.java | |
| 162 | +│ │ ├── Packet.java | |
| 163 | +│ │ └── WAVUtils.java | |
| 164 | +│ └── resources | |
| 165 | +│ ├── app.properties(主配置文件) | |
| 166 | +│ ├── audio.html | |
| 167 | +│ ├── g726 | |
| 168 | +│ │ ├── in_16.g726 | |
| 169 | +│ │ ├── in_24.g726 | |
| 170 | +│ │ ├── in_32.g726 | |
| 171 | +│ │ └── in_40.g726 | |
| 172 | +│ ├── log4j.properties | |
| 173 | +│ ├── multimedia.html(测试用音视频播放页面) | |
| 174 | +│ ├── tcpdump.bin(测试用数据文件,音频ADPCM含海思头,视频H264) | |
| 175 | +│ ├── nginx_sample.conf(NGINX反向代理样例,解决6路并发问题) | |
| 176 | +│ ├── test.html | |
| 177 | +│ └── video.html | |
| 178 | +``` | |
| 179 | + | |
| 180 | +### 项目打包说明 | |
| 181 | +通过**mvn package**直接打包成jar包,通过`java -jar jtt1078-video-server-1.0-SNAPSHOT.jar`即可运行,最好把**app.properties**和**multimedia.html**一并放在同一个目录下,因为项目会优先读取文件系统中的配置文件信息。而如果没有本地测试的需求,**multimedia.html**可以不要。 | |
| 182 | + | |
| 183 | +### 注意事项 | |
| 184 | +1. 本项目为JT 1078协议的流媒体服务器部分的实现,不包括1078协议的控制消息交互部分,就是在0x9101指令下发后,终端连接到的音视频服务器的实现。 | |
| 185 | +2. 在一般的浏览器里,比如Chrome下,浏览器限制了对于同一个域名的连接最多只能够有6个并发,所以如果要同时播放多路视频,需要准备多个域名或是端口,通过轮循分配的方式,把视频的传输连接,分配到不同的URL上去。 | |
| 186 | + | |
| 187 | +### 致谢 | |
| 188 | +本项目一开始只是个简单的示例项目,在开源、建立QQ交流群后,得到了大批的同道中人的帮助和支持,在此表示谢意。本项目尚未完全完善,非常高兴能够有更多的朋友一起加入进来,一起提出更加闪亮的想法,建设更加强大的视频监控平台! | |
| 189 | + | |
| 190 | +### 致谢名单 | |
| 191 | +非常感谢以下网友的帮助和支持,以及其他默默支持的朋友们! | |
| 192 | +* 不岸不名 | |
| 193 | +* 故事~ | |
| 194 | +* 小黄瓜要吃饭 | |
| 195 | +* yedajiang44.com([github.com/yedajiang44](https://github.com/yedajiang44)) | |
| 196 | +* 幸福一定强 | |
| 197 | +* minigps-基站定位服务 | |
| 198 | +* 慢慢 | |
| 199 | +* power LXC | |
| 200 | +* 奎杜 | |
| 201 | +* 孤峰赏月/hx([github/jelycom](https://github.com/jelycom)) | |
| 202 | +* 洛奇([cuiyaonan](https://gitee.com/cuiyaonan2000)) | |
| 203 | +* tmyam | |
| 204 | + | |
| 205 | +### 推荐群友项目 | |
| 206 | +|项目|URL|作者|说明| | |
| 207 | +|---|---|---|---| | |
| 208 | +|JT1078|https://github.com/yedajiang44/JT1078|SmallChi/[yedajiang44](https://github.com/yedajiang44)|C#,支持音视频,通过websocket传输flv到前端| | |
| 209 | + | |
| 210 | +### 交流讨论 | |
| 211 | +QQ群:808432702,加入我们,群里有热心的同道中人、相关资料、测试数据、代码以及各种方案的先行者等着你。 | |
| 212 | + | |
| 213 | +### 捐助 | |
| 214 | +开源不易,请我抽支芙蓉王吧。 | |
| 215 | + | |
| 216 | +<img src="./doc/donate.png" /> | |
| 0 | 217 | \ No newline at end of file | ... | ... |
doc/1078.png
0 → 100644
6.17 KB
doc/donate.png
0 → 100644
23.6 KB
doc/ffmpeg.png
0 → 100644
15.5 KB
pom.xml
0 → 100644
| 1 | +++ a/pom.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | + | |
| 3 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
| 5 | + <modelVersion>4.0.0</modelVersion> | |
| 6 | + | |
| 7 | + <groupId>cn.org.hentai</groupId> | |
| 8 | + <artifactId>jtt1078-video-server</artifactId> | |
| 9 | + <version>1.0-0</version> | |
| 10 | + | |
| 11 | + <name>jtt1078-video-server</name> | |
| 12 | + <url>http://www.hentai.org.cn/</url> | |
| 13 | + | |
| 14 | + <properties> | |
| 15 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
| 16 | + <maven.compiler.source>1.8</maven.compiler.source> | |
| 17 | + <maven.compiler.target>1.8</maven.compiler.target> | |
| 18 | + <!-- logging --> | |
| 19 | + <log4j.version>1.2.12</log4j.version> | |
| 20 | + <slf4j.version>1.7.12</slf4j.version> | |
| 21 | + </properties> | |
| 22 | + | |
| 23 | + <dependencies> | |
| 24 | + <dependency> | |
| 25 | + <groupId>io.netty</groupId> | |
| 26 | + <artifactId>netty-all</artifactId> | |
| 27 | + <version>4.1.42.Final</version> | |
| 28 | + </dependency> | |
| 29 | + <!-- Logging with SLF4J --> | |
| 30 | + <dependency> | |
| 31 | + <groupId>log4j</groupId> | |
| 32 | + <artifactId>log4j</artifactId> | |
| 33 | + <version>${log4j.version}</version> | |
| 34 | + </dependency> | |
| 35 | + <dependency> | |
| 36 | + <groupId>org.slf4j</groupId> | |
| 37 | + <artifactId>slf4j-api</artifactId> | |
| 38 | + <version>${slf4j.version}</version> | |
| 39 | + </dependency> | |
| 40 | + <dependency> | |
| 41 | + <groupId>org.slf4j</groupId> | |
| 42 | + <artifactId>slf4j-log4j12</artifactId> | |
| 43 | + <version>${slf4j.version}</version> | |
| 44 | + </dependency> | |
| 45 | + | |
| 46 | + <dependency> | |
| 47 | + <groupId>net.sf.json-lib</groupId> | |
| 48 | + <artifactId>json-lib</artifactId> | |
| 49 | + <version>2.4</version> | |
| 50 | + <classifier>jdk15</classifier> | |
| 51 | + </dependency> | |
| 52 | + <!--pcm转mp3--> | |
| 53 | + <dependency> | |
| 54 | + <groupId>de.sciss</groupId> | |
| 55 | + <artifactId>jump3r</artifactId> | |
| 56 | + <version>1.0.5</version> | |
| 57 | + </dependency> | |
| 58 | + </dependencies> | |
| 59 | + | |
| 60 | + <build> | |
| 61 | + <plugins> | |
| 62 | + | |
| 63 | + <plugin> | |
| 64 | + <artifactId>maven-assembly-plugin</artifactId> | |
| 65 | + <configuration> | |
| 66 | + <appendAssemblyId>false</appendAssemblyId> | |
| 67 | + <descriptorRefs> | |
| 68 | + <descriptorRef>jar-with-dependencies</descriptorRef> | |
| 69 | + </descriptorRefs> | |
| 70 | + <archive> | |
| 71 | + <manifest> | |
| 72 | + <!-- 此处指定main方法入口的class --> | |
| 73 | + <mainClass>cn.org.hentai.jtt1078.app.VideoServerApp</mainClass> | |
| 74 | + </manifest> | |
| 75 | + </archive> | |
| 76 | + </configuration> | |
| 77 | + <executions> | |
| 78 | + <execution> | |
| 79 | + <id>make-assembly</id> | |
| 80 | + <phase>package</phase> | |
| 81 | + <goals> | |
| 82 | + <goal>assembly</goal> | |
| 83 | + </goals> | |
| 84 | + </execution> | |
| 85 | + </executions> | |
| 86 | + </plugin> | |
| 87 | + | |
| 88 | + </plugins> | |
| 89 | + </build> | |
| 90 | + | |
| 91 | + | |
| 92 | +</project> | ... | ... |
src/main/java/cn/org/hentai/jtt1078/app/VideoServerApp.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/app/VideoServerApp.java | |
| 1 | +package cn.org.hentai.jtt1078.app; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.http.GeneralResponseWriter; | |
| 4 | +import cn.org.hentai.jtt1078.http.NettyHttpServerHandler; | |
| 5 | +import cn.org.hentai.jtt1078.publisher.PublishManager; | |
| 6 | +import cn.org.hentai.jtt1078.server.Jtt1078Handler; | |
| 7 | +import cn.org.hentai.jtt1078.server.Jtt1078MessageDecoder; | |
| 8 | +import cn.org.hentai.jtt1078.server.SessionManager; | |
| 9 | +import cn.org.hentai.jtt1078.util.Configs; | |
| 10 | +import io.netty.bootstrap.ServerBootstrap; | |
| 11 | +import io.netty.channel.*; | |
| 12 | +import io.netty.channel.nio.NioEventLoopGroup; | |
| 13 | +import io.netty.channel.socket.SocketChannel; | |
| 14 | +import io.netty.channel.socket.nio.NioServerSocketChannel; | |
| 15 | +import io.netty.handler.codec.http.HttpObjectAggregator; | |
| 16 | +import io.netty.handler.codec.http.HttpRequestDecoder; | |
| 17 | +import io.netty.handler.codec.http.HttpResponseEncoder; | |
| 18 | +import org.slf4j.Logger; | |
| 19 | +import org.slf4j.LoggerFactory; | |
| 20 | +import sun.misc.Signal; | |
| 21 | +import sun.misc.SignalHandler; | |
| 22 | +import io.netty.handler.timeout.IdleStateHandler; | |
| 23 | +import java.net.InetAddress; | |
| 24 | +import java.util.concurrent.TimeUnit; | |
| 25 | + | |
| 26 | +/** | |
| 27 | + * Created by matrixy on 2019/4/9. | |
| 28 | + */ | |
| 29 | +public class VideoServerApp | |
| 30 | +{ | |
| 31 | + private static Logger logger = LoggerFactory.getLogger(VideoServerApp.class); | |
| 32 | + | |
| 33 | + public static void main(String[] args) throws Exception | |
| 34 | + { | |
| 35 | + Configs.init("/app.properties"); | |
| 36 | + PublishManager.init(); | |
| 37 | + SessionManager.init(); | |
| 38 | + | |
| 39 | + VideoServer videoServer = new VideoServer(); | |
| 40 | + HttpServer httpServer = new HttpServer(); | |
| 41 | + | |
| 42 | + Signal.handle(new Signal("TERM"), new SignalHandler() | |
| 43 | + { | |
| 44 | + @Override | |
| 45 | + public void handle(Signal signal) | |
| 46 | + { | |
| 47 | + videoServer.shutdown(); | |
| 48 | + httpServer.shutdown(); | |
| 49 | + } | |
| 50 | + }); | |
| 51 | + | |
| 52 | + videoServer.start(); | |
| 53 | + httpServer.start(); | |
| 54 | + } | |
| 55 | + | |
| 56 | + static class VideoServer | |
| 57 | + { | |
| 58 | + private static ServerBootstrap serverBootstrap; | |
| 59 | + | |
| 60 | + private static EventLoopGroup bossGroup; | |
| 61 | + private static EventLoopGroup workerGroup; | |
| 62 | + | |
| 63 | + private static void start() throws Exception | |
| 64 | + { | |
| 65 | + serverBootstrap = new ServerBootstrap(); | |
| 66 | + serverBootstrap.option(ChannelOption.SO_BACKLOG, Configs.getInt("server.backlog", 102400)); | |
| 67 | + bossGroup = new NioEventLoopGroup(Configs.getInt("server.worker-count", Runtime.getRuntime().availableProcessors())); | |
| 68 | + workerGroup = new NioEventLoopGroup(); | |
| 69 | + serverBootstrap.group(bossGroup, workerGroup) | |
| 70 | + .channel(NioServerSocketChannel.class) | |
| 71 | + .childHandler(new ChannelInitializer<SocketChannel>() { | |
| 72 | + @Override | |
| 73 | + protected void initChannel(final SocketChannel channel) throws Exception { | |
| 74 | + ChannelPipeline p = channel.pipeline(); | |
| 75 | + // p.addLast(new IdleStateHandler(10,0,0, TimeUnit.SECONDS)); | |
| 76 | + p.addLast(new Jtt1078MessageDecoder()); | |
| 77 | + // p.addLast(new Jtt808MessageEncoder()); | |
| 78 | + // p.addLast(new JTT808Handler()); | |
| 79 | + p.addLast(new Jtt1078Handler()); | |
| 80 | + } | |
| 81 | + }); | |
| 82 | + | |
| 83 | + int port = Configs.getInt("server.port", 1078); | |
| 84 | + Channel ch = serverBootstrap.bind(InetAddress.getByName("0.0.0.0"), port).sync().channel(); | |
| 85 | + logger.info("Video Server started at: {}", port); | |
| 86 | + ch.closeFuture(); | |
| 87 | + } | |
| 88 | + | |
| 89 | + private static void shutdown() | |
| 90 | + { | |
| 91 | + try | |
| 92 | + { | |
| 93 | + bossGroup.shutdownGracefully(); | |
| 94 | + workerGroup.shutdownGracefully(); | |
| 95 | + } | |
| 96 | + catch(Exception e) | |
| 97 | + { | |
| 98 | + e.printStackTrace(); | |
| 99 | + } | |
| 100 | + } | |
| 101 | + } | |
| 102 | + | |
| 103 | + static class HttpServer | |
| 104 | + { | |
| 105 | + private static ServerBootstrap serverBootstrap; | |
| 106 | + | |
| 107 | + private static EventLoopGroup bossGroup; | |
| 108 | + private static EventLoopGroup workerGroup; | |
| 109 | + | |
| 110 | + private static void start() throws Exception | |
| 111 | + { | |
| 112 | + bossGroup = new NioEventLoopGroup(); | |
| 113 | + workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors()); | |
| 114 | + | |
| 115 | + ServerBootstrap bootstrap = new ServerBootstrap(); | |
| 116 | + bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) | |
| 117 | + .childHandler(new ChannelInitializer<SocketChannel>() | |
| 118 | + { | |
| 119 | + @Override | |
| 120 | + public void initChannel(SocketChannel ch) throws Exception | |
| 121 | + { | |
| 122 | + ch.pipeline().addLast( | |
| 123 | + new GeneralResponseWriter(), | |
| 124 | + new HttpResponseEncoder(), | |
| 125 | + new HttpRequestDecoder(), | |
| 126 | + new HttpObjectAggregator(1024 * 64), | |
| 127 | + new NettyHttpServerHandler() | |
| 128 | + ); | |
| 129 | + } | |
| 130 | + }).option(ChannelOption.SO_BACKLOG, 1024) | |
| 131 | + .childOption(ChannelOption.SO_KEEPALIVE, true); | |
| 132 | + try | |
| 133 | + { | |
| 134 | + int port = Configs.getInt("server.http.port", 3333); | |
| 135 | + ChannelFuture f = bootstrap.bind(InetAddress.getByName("0.0.0.0"), port).sync(); | |
| 136 | + logger.info("HTTP Server started at: {}", port); | |
| 137 | + f.channel().closeFuture().sync(); | |
| 138 | + } | |
| 139 | + catch (InterruptedException e) | |
| 140 | + { | |
| 141 | + logger.error("http server error", e); | |
| 142 | + } | |
| 143 | + finally | |
| 144 | + { | |
| 145 | + workerGroup.shutdownGracefully(); | |
| 146 | + bossGroup.shutdownGracefully(); | |
| 147 | + } | |
| 148 | + } | |
| 149 | + | |
| 150 | + private static void shutdown() | |
| 151 | + { | |
| 152 | + try | |
| 153 | + { | |
| 154 | + bossGroup.shutdownGracefully(); | |
| 155 | + workerGroup.shutdownGracefully(); | |
| 156 | + } | |
| 157 | + catch(Exception e) | |
| 158 | + { | |
| 159 | + e.printStackTrace(); | |
| 160 | + } | |
| 161 | + } | |
| 162 | + } | |
| 163 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/ADPCMCodec.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/ADPCMCodec.java | |
| 1 | +package cn.org.hentai.jtt1078.codec; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.server.Jtt1078Decoder; | |
| 4 | +import cn.org.hentai.jtt1078.util.ByteHolder; | |
| 5 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 6 | + | |
| 7 | +import java.io.ByteArrayInputStream; | |
| 8 | +import java.io.ByteArrayOutputStream; | |
| 9 | +import java.io.FileInputStream; | |
| 10 | +import java.io.FileOutputStream; | |
| 11 | +import java.util.Arrays; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * Created by houcheng on 2019-12-05. | |
| 15 | + * ADPCM 和 PCM转换 | |
| 16 | + */ | |
| 17 | +public final class ADPCMCodec extends AudioCodec | |
| 18 | +{ | |
| 19 | + static int[] indexTable = { | |
| 20 | + -1, -1, -1, -1, 2, 4, 6, 8, | |
| 21 | + -1, -1, -1, -1, 2, 4, 6, 8 | |
| 22 | + }; | |
| 23 | + | |
| 24 | + static int[] stepsizeTable = { | |
| 25 | + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, | |
| 26 | + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, | |
| 27 | + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, | |
| 28 | + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, | |
| 29 | + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, | |
| 30 | + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, | |
| 31 | + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, | |
| 32 | + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | |
| 33 | + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 | |
| 34 | + }; | |
| 35 | + | |
| 36 | + public static class State | |
| 37 | + { | |
| 38 | + public short valprev; | |
| 39 | + public byte index; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public byte[] toPCM(byte[] data) | |
| 43 | + { | |
| 44 | + State state = new State(); | |
| 45 | + int dlen = data.length / 2; | |
| 46 | + byte[] temp; | |
| 47 | + // 如果前四字节是00 01 52 00,则是海思头,需要去掉,否则就视为普通的ADPCM编码 | |
| 48 | + if (data[0] == 0x00 && data[1] == 0x01 && (data[2] & 0xff) == (data.length - 4) / 2 && data[3] == 0x00) | |
| 49 | + { | |
| 50 | + dlen = (data.length - 8); | |
| 51 | + temp = new byte[data.length - 8]; | |
| 52 | + System.arraycopy(data, 8, temp, 0, temp.length); | |
| 53 | + | |
| 54 | + state.valprev = (short)(((data[5] << 8) & 0xff00) | (data[4] & 0xff)); | |
| 55 | + state.index = data[6]; | |
| 56 | + } | |
| 57 | + else | |
| 58 | + { | |
| 59 | + dlen = data.length - 4; | |
| 60 | + temp = new byte[data.length - 4]; | |
| 61 | + System.arraycopy(data, 4, temp, 0, temp.length); | |
| 62 | + | |
| 63 | + state.valprev = (short)(((data[1] << 8) & 0xff00) | (data[0] & 0xff)); | |
| 64 | + state.index = data[2]; | |
| 65 | + } | |
| 66 | + short[] outdata = new short[dlen * 2]; | |
| 67 | + adpcm_decoder(temp, outdata, dlen * 2, state); | |
| 68 | + temp = new byte[dlen * 4]; | |
| 69 | + for (int i = 0, k = 0; i < outdata.length; i++) | |
| 70 | + { | |
| 71 | + short s = outdata[i]; | |
| 72 | + temp[k++] = (byte)(s & 0xff); | |
| 73 | + temp[k++] = (byte)((s >> 8) & 0xff); | |
| 74 | + } | |
| 75 | + return temp; | |
| 76 | + } | |
| 77 | + | |
| 78 | + public byte[] fromPCM(byte[] data) | |
| 79 | + { | |
| 80 | + return null; | |
| 81 | + } | |
| 82 | + | |
| 83 | + public static void adpcm_coder(short[] indata, byte[] outdata, int len, State state) | |
| 84 | + { | |
| 85 | + int val; /* Current input sample value */ | |
| 86 | + int sign; /* Current adpcm sign bit */ | |
| 87 | + int delta; /* Current adpcm output value */ | |
| 88 | + int diff; /* Difference between val and valprev */ | |
| 89 | + int step; /* Stepsize */ | |
| 90 | + int valpred; /* Predicted output value */ | |
| 91 | + int vpdiff; /* Current change to valpred */ | |
| 92 | + int index; /* Current step change index */ | |
| 93 | + int outputbuffer = 0; /* place to keep previous 4-bit value */ | |
| 94 | + int bufferstep; /* toggle between outputbuffer/output */ | |
| 95 | + | |
| 96 | + byte[] outp = outdata; | |
| 97 | + short[] inp = indata; | |
| 98 | + | |
| 99 | + valpred = state.valprev; | |
| 100 | + index = state.index; | |
| 101 | + step = stepsizeTable[index]; | |
| 102 | + | |
| 103 | + bufferstep = 1; | |
| 104 | + | |
| 105 | + int k = 0; | |
| 106 | + for ( int i = 0; len > 0 ; len--, i++) { | |
| 107 | + val = inp[i]; | |
| 108 | + | |
| 109 | + /* Step 1 - compute difference with previous value */ | |
| 110 | + diff = val - valpred; | |
| 111 | + sign = (diff < 0) ? 8 : 0; | |
| 112 | + if ( sign != 0) diff = (-diff); | |
| 113 | + | |
| 114 | + /* Step 2 - Divide and clamp */ | |
| 115 | + /* Note: | |
| 116 | + ** This code *approximately* computes: | |
| 117 | + ** delta = diff*4/step; | |
| 118 | + ** vpdiff = (delta+0.5)*step/4; | |
| 119 | + ** but in shift step bits are dropped. The net result of this is | |
| 120 | + ** that even if you have fast mul/div hardware you cannot put it to | |
| 121 | + ** good use since the fixup would be too expensive. | |
| 122 | + */ | |
| 123 | + delta = 0; | |
| 124 | + vpdiff = (step >> 3); | |
| 125 | + | |
| 126 | + if ( diff >= step ) { | |
| 127 | + delta = 4; | |
| 128 | + diff -= step; | |
| 129 | + vpdiff += step; | |
| 130 | + } | |
| 131 | + step >>= 1; | |
| 132 | + if ( diff >= step ) { | |
| 133 | + delta |= 2; | |
| 134 | + diff -= step; | |
| 135 | + vpdiff += step; | |
| 136 | + } | |
| 137 | + step >>= 1; | |
| 138 | + if ( diff >= step ) { | |
| 139 | + delta |= 1; | |
| 140 | + vpdiff += step; | |
| 141 | + } | |
| 142 | + | |
| 143 | + /* Step 3 - Update previous value */ | |
| 144 | + if ( sign != 0 ) | |
| 145 | + valpred -= vpdiff; | |
| 146 | + else | |
| 147 | + valpred += vpdiff; | |
| 148 | + | |
| 149 | + /* Step 4 - Clamp previous value to 16 bits */ | |
| 150 | + if ( valpred > 32767 ) | |
| 151 | + valpred = 32767; | |
| 152 | + else if ( valpred < -32768 ) | |
| 153 | + valpred = -32768; | |
| 154 | + | |
| 155 | + /* Step 5 - Assemble value, update index and step values */ | |
| 156 | + delta |= sign; | |
| 157 | + | |
| 158 | + index += indexTable[delta]; | |
| 159 | + if ( index < 0 ) index = 0; | |
| 160 | + if ( index > 88 ) index = 88; | |
| 161 | + step = stepsizeTable[index]; | |
| 162 | + | |
| 163 | + /* Step 6 - Output value */ | |
| 164 | + if ( bufferstep != 0 ) { | |
| 165 | + outputbuffer = (delta << 4) & 0xf0; | |
| 166 | + } else { | |
| 167 | + outp[k++] = (byte)((delta & 0x0f) | outputbuffer); | |
| 168 | + } | |
| 169 | + bufferstep = bufferstep == 0 ? 1 : 0; | |
| 170 | + } | |
| 171 | + | |
| 172 | + /* Output last step, if needed */ | |
| 173 | + if ( bufferstep == 0 ) | |
| 174 | + outp[k++] = (byte)outputbuffer; | |
| 175 | + | |
| 176 | + state.valprev = (short)valpred; | |
| 177 | + state.index = (byte)index; | |
| 178 | + } | |
| 179 | + | |
| 180 | + | |
| 181 | + public static void adpcm_decoder(byte[] indata, short[] outdata, int len, State state) | |
| 182 | + { | |
| 183 | + // signed char *inp; /* Input buffer pointer */ | |
| 184 | + // short *outp; /* output buffer pointer */ | |
| 185 | + int sign; /* Current adpcm sign bit */ | |
| 186 | + int delta; /* Current adpcm output value */ | |
| 187 | + int step; /* Stepsize */ | |
| 188 | + int valpred; /* Predicted value */ | |
| 189 | + int vpdiff; /* Current change to valpred */ | |
| 190 | + int index; /* Current step change index */ | |
| 191 | + int inputbuffer = 0; /* place to keep next 4-bit value */ | |
| 192 | + int bufferstep; /* toggle between inputbuffer/input */ | |
| 193 | + | |
| 194 | + short[] outp = outdata; | |
| 195 | + byte[] inp = indata; | |
| 196 | + | |
| 197 | + valpred = state.valprev; | |
| 198 | + index = state.index; | |
| 199 | + if ( index < 0 ) index = 0; | |
| 200 | + if ( index > 88 ) index = 88; | |
| 201 | + step = stepsizeTable[index]; | |
| 202 | + | |
| 203 | + bufferstep = 0; | |
| 204 | + | |
| 205 | + int k = 0; | |
| 206 | + for ( int i = 0; len > 0 ; len-- ) { | |
| 207 | + | |
| 208 | + /* Step 1 - get the delta value */ | |
| 209 | + if ( bufferstep != 0 ) { | |
| 210 | + delta = inputbuffer & 0xf; | |
| 211 | + } else { | |
| 212 | + inputbuffer = inp[i++]; | |
| 213 | + delta = (inputbuffer >> 4) & 0xf; | |
| 214 | + } | |
| 215 | + bufferstep = bufferstep == 0 ? 1 : 0; | |
| 216 | + | |
| 217 | + /* Step 2 - Find new index value (for later) */ | |
| 218 | + index += indexTable[delta]; | |
| 219 | + if ( index < 0 ) index = 0; | |
| 220 | + if ( index > 88 ) index = 88; | |
| 221 | + | |
| 222 | + /* Step 3 - Separate sign and magnitude */ | |
| 223 | + sign = delta & 8; | |
| 224 | + delta = delta & 7; | |
| 225 | + | |
| 226 | + /* Step 4 - Compute difference and new predicted value */ | |
| 227 | + /* | |
| 228 | + ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment | |
| 229 | + ** in adpcm_coder. | |
| 230 | + */ | |
| 231 | + vpdiff = step >> 3; | |
| 232 | + if ( (delta & 4) > 0 ) vpdiff += step; | |
| 233 | + if ( (delta & 2) > 0 ) vpdiff += step>>1; | |
| 234 | + if ( (delta & 1) > 0 ) vpdiff += step>>2; | |
| 235 | + | |
| 236 | + if ( sign != 0 ) | |
| 237 | + valpred -= vpdiff; | |
| 238 | + else | |
| 239 | + valpred += vpdiff; | |
| 240 | + | |
| 241 | + /* Step 5 - clamp output value */ | |
| 242 | + if ( valpred > 32767 ) | |
| 243 | + valpred = 32767; | |
| 244 | + else if ( valpred < -32768 ) | |
| 245 | + valpred = -32768; | |
| 246 | + | |
| 247 | + /* Step 6 - Update step value */ | |
| 248 | + step = stepsizeTable[index]; | |
| 249 | + | |
| 250 | + /* Step 7 - Output value */ | |
| 251 | + outp[k++] = (short)valpred; | |
| 252 | + } | |
| 253 | + | |
| 254 | + state.valprev = (short)valpred; | |
| 255 | + state.index = (byte)index; | |
| 256 | + } | |
| 257 | + | |
| 258 | + | |
| 259 | + public static void main(String[] args) throws Exception | |
| 260 | + { | |
| 261 | + ByteArrayInputStream bais = null; | |
| 262 | + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024 * 1024 * 4); | |
| 263 | + | |
| 264 | + int len = -1; | |
| 265 | + byte[] block = new byte[512]; | |
| 266 | + FileInputStream fis = new FileInputStream("d:\\test\\g711\\streamax.bin"); | |
| 267 | + FileOutputStream fos = new FileOutputStream("d:\\test\\g711\\111111111122222222222222.pcm"); | |
| 268 | + | |
| 269 | + ADPCMCodec codec = new ADPCMCodec(); | |
| 270 | + | |
| 271 | + Jtt1078Decoder decoder = new Jtt1078Decoder(); | |
| 272 | + while ((len = fis.read(block)) > -1) | |
| 273 | + { | |
| 274 | + decoder.write(block, 0, len); | |
| 275 | + while (true) | |
| 276 | + { | |
| 277 | + Packet p = decoder.decode(); | |
| 278 | + if (p == null) break; | |
| 279 | + | |
| 280 | + int lengthOffset = 28; | |
| 281 | + int dataType = (p.seek(15).nextByte() >> 4) & 0x0f; | |
| 282 | + // 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段 | |
| 283 | + if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; | |
| 284 | + else if (dataType == 0x03) lengthOffset = 28 - 4; | |
| 285 | + | |
| 286 | + // FFMpegManager.getInstance().feed(publisherId, packet.seek(lengthOffset + 2).nextBytes()); | |
| 287 | + if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) | |
| 288 | + { | |
| 289 | + | |
| 290 | + } | |
| 291 | + else | |
| 292 | + { | |
| 293 | + byte[] data = p.seek(lengthOffset + 2).nextBytes(); | |
| 294 | + fos.write(codec.toPCM(data)); | |
| 295 | + fos.flush(); | |
| 296 | + } | |
| 297 | + } | |
| 298 | + } | |
| 299 | + | |
| 300 | + fos.flush(); | |
| 301 | + | |
| 302 | + fis.close(); | |
| 303 | + fos.close(); | |
| 304 | + } | |
| 305 | + | |
| 306 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/AudioCodec.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/AudioCodec.java | |
| 1 | +package cn.org.hentai.jtt1078.codec; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.entity.MediaEncoding; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Created by houcheng on 2019-12-11. | |
| 7 | + */ | |
| 8 | +public abstract class AudioCodec | |
| 9 | +{ | |
| 10 | + public abstract byte[] toPCM(byte[] data); | |
| 11 | + public abstract byte[] fromPCM(byte[] data); | |
| 12 | + | |
| 13 | + public static AudioCodec getCodec(int encoding) | |
| 14 | + { | |
| 15 | + if (MediaEncoding.Encoding.ADPCMA.ordinal() == encoding) return new ADPCMCodec(); | |
| 16 | + else if (MediaEncoding.Encoding.G711A.ordinal() == encoding) return new G711Codec(); | |
| 17 | + else if (MediaEncoding.Encoding.G711U.ordinal() == encoding) return new G711UCodec(); | |
| 18 | + else if (MediaEncoding.Encoding.G726.ordinal() == encoding) return new G726Codec(); | |
| 19 | + // else if (Audio.Encoding.G726.equals(encoding)) ; | |
| 20 | + else return new SilenceCodec(); | |
| 21 | + } | |
| 22 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/G711Codec.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/G711Codec.java | |
| 1 | +package cn.org.hentai.jtt1078.codec; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.AudioCodec; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * 核心转换,PCM转G711 | |
| 7 | + * Created by onlygx | |
| 8 | + */ | |
| 9 | +public class G711Codec extends AudioCodec | |
| 10 | +{ | |
| 11 | + private final static int SIGN_BIT = 0x80; | |
| 12 | + private final static int QUANT_MASK = 0xf; | |
| 13 | + private final static int SEG_SHIFT = 4; | |
| 14 | + private final static int SEG_MASK = 0x70; | |
| 15 | + static short[] seg_end = {0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; | |
| 16 | + private final static int cClip = 32635; | |
| 17 | + private static final byte[] aLawCompressTable = new byte[]{1, 1, 2, 2, 3, 3, 3, | |
| 18 | + 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, | |
| 19 | + 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, | |
| 20 | + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, | |
| 21 | + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | |
| 22 | + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | |
| 23 | + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; | |
| 24 | + | |
| 25 | + private static byte linearToALawSample(short sample) { | |
| 26 | + int sign; | |
| 27 | + int exponent; | |
| 28 | + int mantissa; | |
| 29 | + int s; | |
| 30 | + | |
| 31 | + sign = ((~sample) >> 8) & 0x80; | |
| 32 | + if (!(sign == 0x80)) { | |
| 33 | + sample = (short) -sample; | |
| 34 | + } | |
| 35 | + if (sample > cClip) { | |
| 36 | + sample = cClip; | |
| 37 | + } | |
| 38 | + if (sample >= 256) { | |
| 39 | + exponent = aLawCompressTable[(sample >> 8) & 0x7F]; | |
| 40 | + mantissa = (sample >> (exponent + 3)) & 0x0F; | |
| 41 | + s = (exponent << 4) | mantissa; | |
| 42 | + } else { | |
| 43 | + s = sample >> 4; | |
| 44 | + } | |
| 45 | + s ^= (sign ^ 0x55); | |
| 46 | + return (byte) s; | |
| 47 | + } | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * PCM转G711 | |
| 51 | + * | |
| 52 | + * @param src 编码前的数据 | |
| 53 | + * @return 编码后res数组长度应为编码前src数组长度的一半 | |
| 54 | + */ | |
| 55 | + public static byte[] encode(byte[] src) { | |
| 56 | + int j = 0; | |
| 57 | + int len = src.length; | |
| 58 | + int count = len / 2; | |
| 59 | + byte[] res = new byte[count]; | |
| 60 | + short sample = 0; | |
| 61 | + for (int i = 0; i < count; i++) { | |
| 62 | + sample = (short) (((src[j++] & 0xff) | (src[j++]) << 8)); | |
| 63 | + res[i] = linearToALawSample(sample); | |
| 64 | + } | |
| 65 | + return res; | |
| 66 | + } | |
| 67 | + | |
| 68 | + static short search(short val, short[] table, short size) { | |
| 69 | + | |
| 70 | + for (short i = 0; i < size; i++) { | |
| 71 | + if (val <= table[i]) { | |
| 72 | + return i; | |
| 73 | + } | |
| 74 | + } | |
| 75 | + return size; | |
| 76 | + } | |
| 77 | + | |
| 78 | + public static byte linear2alaw(short pcm_val) { | |
| 79 | + short mask; | |
| 80 | + short seg; | |
| 81 | + char aval; | |
| 82 | + if (pcm_val >= 0) { | |
| 83 | + mask = 0xD5; | |
| 84 | + } else { | |
| 85 | + mask = 0x55; | |
| 86 | + pcm_val = (short) (-pcm_val - 1); | |
| 87 | + } | |
| 88 | + | |
| 89 | + /* Convert the scaled magnitude to segment number. */ | |
| 90 | + seg = search(pcm_val, seg_end, (short) 8); | |
| 91 | + | |
| 92 | + /* Combine the sign, segment, and quantization bits. */ | |
| 93 | + | |
| 94 | + if (seg >= 8) /* out of range, return maximum value. */ return (byte) (0x7F ^ mask); | |
| 95 | + else { | |
| 96 | + aval = (char) (seg << SEG_SHIFT); | |
| 97 | + if (seg < 2) aval |= (pcm_val >> 4) & QUANT_MASK; | |
| 98 | + else aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; | |
| 99 | + return (byte) (aval ^ mask); | |
| 100 | + } | |
| 101 | + } | |
| 102 | + | |
| 103 | + | |
| 104 | + public static short alaw2linear(byte a_val) { | |
| 105 | + short t; | |
| 106 | + short seg; | |
| 107 | + | |
| 108 | + a_val ^= 0x55; | |
| 109 | + | |
| 110 | + t = (short) ((a_val & QUANT_MASK) << 4); | |
| 111 | + seg = (short) ((a_val & SEG_MASK) >> SEG_SHIFT); | |
| 112 | + switch (seg) { | |
| 113 | + case 0: | |
| 114 | + t += 8; | |
| 115 | + break; | |
| 116 | + case 1: | |
| 117 | + t += 0x108; | |
| 118 | + break; | |
| 119 | + default: | |
| 120 | + t += 0x108; | |
| 121 | + t <<= seg - 1; | |
| 122 | + } | |
| 123 | + return (a_val & SIGN_BIT) != 0 ? t : (short) -t; | |
| 124 | + } | |
| 125 | + | |
| 126 | + // 由G.711转至PCM | |
| 127 | + public static byte[] _toPCM(byte[] g711data) { | |
| 128 | + byte[] pcmdata = new byte[g711data.length * 2]; | |
| 129 | + for (int i = 0, k = 0; i < g711data.length; i++) { | |
| 130 | + short v = alaw2linear(g711data[i]); | |
| 131 | + pcmdata[k++] = (byte) (v & 0xff); | |
| 132 | + pcmdata[k++] = (byte) ((v >> 8) & 0xff); | |
| 133 | + } | |
| 134 | + return pcmdata; | |
| 135 | + } | |
| 136 | + | |
| 137 | + // 由PCM转至G.711 | |
| 138 | + public static byte[] _fromPCM(byte[] pcmData) { | |
| 139 | + return encode(pcmData); | |
| 140 | + } | |
| 141 | + | |
| 142 | + @Override | |
| 143 | + public byte[] toPCM(byte[] data) { | |
| 144 | + byte[] temp; | |
| 145 | + // 如果前四字节是00 01 52 00,则是海思头,需要去掉 | |
| 146 | + if (data[0] == 0x00 && data[1] == 0x01 && (data[2] & 0xff) == (data.length - 4) / 2 && data[3] == 0x00) { | |
| 147 | + temp = new byte[data.length - 4]; | |
| 148 | + System.arraycopy(data, 4, temp, 0, temp.length); | |
| 149 | + } else temp = data; | |
| 150 | + | |
| 151 | + return _toPCM(temp); | |
| 152 | + } | |
| 153 | + | |
| 154 | + @Override | |
| 155 | + public byte[] fromPCM(byte[] data) { | |
| 156 | + return encode(data); | |
| 157 | + } | |
| 158 | +} | |
| 0 | 159 | \ No newline at end of file | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/G711UCodec.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/G711UCodec.java | |
| 1 | +package cn.org.hentai.jtt1078.codec; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.util.ByteUtils; | |
| 4 | + | |
| 5 | +import java.io.ByteArrayOutputStream; | |
| 6 | +import java.io.FileInputStream; | |
| 7 | +import java.io.FileOutputStream; | |
| 8 | +/* | |
| 9 | + * This source code is a product of Sun Microsystems, Inc. and is provided | |
| 10 | + * for unrestricted use. Users may copy or modify this source code without | |
| 11 | + * charge. | |
| 12 | + * | |
| 13 | + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING | |
| 14 | + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR | |
| 15 | + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. | |
| 16 | + * | |
| 17 | + * Sun source code is provided with no support and without any obligation on | |
| 18 | + * the part of Sun Microsystems, Inc. to assist in its use, correction, | |
| 19 | + * modification or enhancement. | |
| 20 | + * | |
| 21 | + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE | |
| 22 | + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE | |
| 23 | + * OR ANY PART THEREOF. | |
| 24 | + * | |
| 25 | + * In no event will Sun Microsystems, Inc. be liable for any lost revenue | |
| 26 | + * or profits or other special, indirect and consequential damages, even if | |
| 27 | + * Sun has been advised of the possibility of such damages. | |
| 28 | + * | |
| 29 | + * Sun Microsystems, Inc. | |
| 30 | + * 2550 Garcia Avenue | |
| 31 | + * Mountain View, California 94043 | |
| 32 | + */ | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * Created by houcheng on 2019-12-11. | |
| 36 | + */ | |
| 37 | +public class G711UCodec extends AudioCodec | |
| 38 | +{ | |
| 39 | + static final int ULAW = 1; | |
| 40 | + static final int ALAW = 2; | |
| 41 | + | |
| 42 | + /* 16384 entries per table (16 bit) */ | |
| 43 | + static byte[] linear_to_ulaw = new byte[65536]; | |
| 44 | + | |
| 45 | + /* 16384 entries per table (8 bit) */ | |
| 46 | + static short[] ulaw_to_linear = new short[256]; | |
| 47 | + | |
| 48 | + static final int SIGN_BIT = 0x80; | |
| 49 | + static final int QUANT_MASK = 0x0f; | |
| 50 | + static final int NSEGS = 0x08; | |
| 51 | + static final int SEG_SHIFT = 0x04; | |
| 52 | + static final int SEG_MASK = 0x70; | |
| 53 | + | |
| 54 | + static final int BIAS = 0x84; | |
| 55 | + static final int CLIP = 8159; | |
| 56 | + | |
| 57 | + static short[] seg_aend = { 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF }; | |
| 58 | + static short[] seg_uend = { 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF }; | |
| 59 | + | |
| 60 | + int[] _u2a = { /* u- to A-law conversions */ | |
| 61 | + 1, 1, 2, 2, 3, 3, 4, 4, | |
| 62 | + 5, 5, 6, 6, 7, 7, 8, 8, | |
| 63 | + 9, 10, 11, 12, 13, 14, 15, 16, | |
| 64 | + 17, 18, 19, 20, 21, 22, 23, 24, | |
| 65 | + 25, 27, 29, 31, 33, 34, 35, 36, | |
| 66 | + 37, 38, 39, 40, 41, 42, 43, 44, | |
| 67 | + 46, 48, 49, 50, 51, 52, 53, 54, | |
| 68 | + 55, 56, 57, 58, 59, 60, 61, 62, | |
| 69 | + 64, 65, 66, 67, 68, 69, 70, 71, | |
| 70 | + 72, 73, 74, 75, 76, 77, 78, 79, | |
| 71 | + /* corrected: | |
| 72 | + 81, 82, 83, 84, 85, 86, 87, 88, | |
| 73 | + should be: */ | |
| 74 | + 80, 82, 83, 84, 85, 86, 87, 88, | |
| 75 | + 89, 90, 91, 92, 93, 94, 95, 96, | |
| 76 | + 97, 98, 99, 100, 101, 102, 103, 104, | |
| 77 | + 105, 106, 107, 108, 109, 110, 111, 112, | |
| 78 | + 113, 114, 115, 116, 117, 118, 119, 120, | |
| 79 | + 121, 122, 123, 124, 125, 126, 127, 128}; | |
| 80 | + | |
| 81 | + int[] _a2u = { /* A- to u-law conversions */ | |
| 82 | + 1, 3, 5, 7, 9, 11, 13, 15, | |
| 83 | + 16, 17, 18, 19, 20, 21, 22, 23, | |
| 84 | + 24, 25, 26, 27, 28, 29, 30, 31, | |
| 85 | + 32, 32, 33, 33, 34, 34, 35, 35, | |
| 86 | + 36, 37, 38, 39, 40, 41, 42, 43, | |
| 87 | + 44, 45, 46, 47, 48, 48, 49, 49, | |
| 88 | + 50, 51, 52, 53, 54, 55, 56, 57, | |
| 89 | + 58, 59, 60, 61, 62, 63, 64, 64, | |
| 90 | + 65, 66, 67, 68, 69, 70, 71, 72, | |
| 91 | + /* corrected: | |
| 92 | + 73, 74, 75, 76, 77, 78, 79, 79, | |
| 93 | + should be: */ | |
| 94 | + 73, 74, 75, 76, 77, 78, 79, 80, | |
| 95 | + 80, 81, 82, 83, 84, 85, 86, 87, | |
| 96 | + 88, 89, 90, 91, 92, 93, 94, 95, | |
| 97 | + 96, 97, 98, 99, 100, 101, 102, 103, | |
| 98 | + 104, 105, 106, 107, 108, 109, 110, 111, | |
| 99 | + 112, 113, 114, 115, 116, 117, 118, 119, | |
| 100 | + 120, 121, 122, 123, 124, 125, 126, 127}; | |
| 101 | + | |
| 102 | + static | |
| 103 | + { | |
| 104 | + // 初始化ulaw表 | |
| 105 | + for (int i = 0; i < 256; i++) ulaw_to_linear[i] = ulaw2linear((byte)i); | |
| 106 | + // 初始化ulaw2linear表 | |
| 107 | + for (int i = 0; i < 65535; i++) linear_to_ulaw[i] = linear2ulaw((short)i); | |
| 108 | + } | |
| 109 | + | |
| 110 | + public static short ulaw2linear(byte u_val) | |
| 111 | + { | |
| 112 | + short t; | |
| 113 | + u_val = (byte)(~u_val); | |
| 114 | + t = (short)(((u_val & QUANT_MASK) << 3) + BIAS); | |
| 115 | + t <<= (u_val & SEG_MASK) >>> SEG_SHIFT; | |
| 116 | + | |
| 117 | + return ((u_val & SIGN_BIT) > 0 ? (short)(BIAS - t) : (short)(t - BIAS)); | |
| 118 | + } | |
| 119 | + | |
| 120 | + public static byte linear2ulaw(short pcm_val) | |
| 121 | + { | |
| 122 | + short mask; | |
| 123 | + short seg; | |
| 124 | + byte uval; | |
| 125 | + | |
| 126 | + pcm_val = (short)(pcm_val >> 2); | |
| 127 | + if (pcm_val < 0) | |
| 128 | + { | |
| 129 | + pcm_val = (short)(-pcm_val); | |
| 130 | + mask = 0x7f; | |
| 131 | + } | |
| 132 | + else | |
| 133 | + { | |
| 134 | + mask = 0xff; | |
| 135 | + } | |
| 136 | + | |
| 137 | + if (pcm_val > CLIP) pcm_val = CLIP; | |
| 138 | + pcm_val += (BIAS >> 2); | |
| 139 | + | |
| 140 | + seg = search(pcm_val, seg_uend, (short)8); | |
| 141 | + | |
| 142 | + if (seg >= 8) | |
| 143 | + { | |
| 144 | + return (byte)(0x7f ^ mask); | |
| 145 | + } | |
| 146 | + else | |
| 147 | + { | |
| 148 | + uval = (byte) ((seg << 4) | ((pcm_val >> (seg + 1)) & 0xF)); | |
| 149 | + return (byte)(uval ^ mask); | |
| 150 | + } | |
| 151 | + } | |
| 152 | + | |
| 153 | + static short search(short val, short[] table, short size) | |
| 154 | + { | |
| 155 | + for (short i = 0; i < size; i++) | |
| 156 | + { | |
| 157 | + if (val <= table[i]) return i; | |
| 158 | + } | |
| 159 | + return size; | |
| 160 | + } | |
| 161 | + | |
| 162 | + static void ulaw_to_pcm16(int src_length, byte[] src_samples, byte[] dst_samples) | |
| 163 | + { | |
| 164 | + for (int i = 0, k = 0; i < src_length; i++) | |
| 165 | + { | |
| 166 | + short s = ulaw_to_linear[src_samples[i] & 0xff]; | |
| 167 | + dst_samples[k++] = (byte)(s & 0xff); | |
| 168 | + dst_samples[k++] = (byte)((s >> 8) & 0xff); | |
| 169 | + } | |
| 170 | + } | |
| 171 | + | |
| 172 | + static void pcm16_to_ulaw(int src_length, byte[] src_samples, byte[] dst_samples) | |
| 173 | + { | |
| 174 | + short[] s_samples = ByteUtils.toShortArray(src_samples); | |
| 175 | + for (int i = 0, k = 0; i < s_samples.length; i++) | |
| 176 | + { | |
| 177 | + dst_samples[k++] = linear2ulaw(s_samples[i]); | |
| 178 | + } | |
| 179 | + } | |
| 180 | + | |
| 181 | + @Override | |
| 182 | + public byte[] toPCM(byte[] data) | |
| 183 | + { | |
| 184 | + byte[] temp; | |
| 185 | + // 如果前四字节是00 01 52 00,则是海思头,需要去掉 | |
| 186 | + if (data[0] == 0x00 && data[1] == 0x01 && (data[2] & 0xff) == (data.length - 4) / 2 && data[3] == 0x00) | |
| 187 | + { | |
| 188 | + temp = new byte[data.length - 4]; | |
| 189 | + System.arraycopy(data, 4, temp, 0, temp.length); | |
| 190 | + } | |
| 191 | + else temp = data; | |
| 192 | + | |
| 193 | + byte[] dest = new byte[temp.length * 2]; | |
| 194 | + ulaw_to_pcm16(temp.length, temp, dest); | |
| 195 | + return dest; | |
| 196 | + } | |
| 197 | + | |
| 198 | + @Override | |
| 199 | + public byte[] fromPCM(byte[] data) | |
| 200 | + { | |
| 201 | + byte[] dest = new byte[data.length / 2]; | |
| 202 | + pcm16_to_ulaw(data.length, data, dest); | |
| 203 | + return dest; | |
| 204 | + } | |
| 205 | + | |
| 206 | + public static void main(String[] args) throws Exception | |
| 207 | + { | |
| 208 | + FileInputStream fis = new FileInputStream("d:\\fuck121212121.pcm"); | |
| 209 | + int len = -1; | |
| 210 | + byte[] buff = new byte[320]; | |
| 211 | + AudioCodec codec = new G711UCodec(); | |
| 212 | + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096 * 1024); | |
| 213 | + while ((len = fis.read(buff)) > -1) | |
| 214 | + { | |
| 215 | + baos.write(buff, 0, len); | |
| 216 | + } | |
| 217 | + new FileOutputStream("D:\\temp\\fuckfuckfuck.g711u").write(codec.fromPCM(baos.toByteArray())); | |
| 218 | + } | |
| 219 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/G726Codec.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/G726Codec.java | |
| 1 | +package cn.org.hentai.jtt1078.codec; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.g726.*; | |
| 4 | + | |
| 5 | +import java.io.FileInputStream; | |
| 6 | +import java.io.FileOutputStream; | |
| 7 | + | |
| 8 | +public class G726Codec extends AudioCodec { | |
| 9 | + | |
| 10 | + // pcm采样率 | |
| 11 | + private static final int PCM_SAMPLE = 8000; | |
| 12 | + | |
| 13 | + // pcm采样点 | |
| 14 | + private static final int PCM_POINT = 320; | |
| 15 | + | |
| 16 | + // 音频通道数 | |
| 17 | + private static final int CHANNEL = 1; | |
| 18 | + | |
| 19 | + // 码率 | |
| 20 | + private static final int G726_BIT_RATE_16000 = 16000; | |
| 21 | + private static final int G726_BIT_RATE_24000 = 24000; | |
| 22 | + private static final int G726_BIT_RATE_32000 = 32000; | |
| 23 | + private static final int G726_BIT_RATE_40000 = 40000; | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public byte[] toPCM(byte[] data) { | |
| 29 | + int pos = 0; | |
| 30 | + // 如果前四字节是00 01 52 00,则是海思头,需要去掉 | |
| 31 | + if (data[0] == 0x00 && data[1] == 0x01 && (data[2] & 0xff) == (data.length - 4) / 2 && data[3] == 0x00) { | |
| 32 | + pos = 4; | |
| 33 | + } | |
| 34 | + | |
| 35 | + int length = data.length - pos; | |
| 36 | + | |
| 37 | + int point = PCM_POINT; | |
| 38 | + | |
| 39 | + // 计算G726的码率 | |
| 40 | + int rateBit = length * 8 * PCM_SAMPLE/point; | |
| 41 | + | |
| 42 | + G726 g726 = null; | |
| 43 | + | |
| 44 | + // 码率 | |
| 45 | + if (rateBit == G726_BIT_RATE_40000) { | |
| 46 | + g726 = new G726_40(); | |
| 47 | + } | |
| 48 | + else if (rateBit == G726_BIT_RATE_32000) { | |
| 49 | + g726 = new G726_32(); | |
| 50 | + } | |
| 51 | + else if (rateBit == G726_BIT_RATE_24000) { | |
| 52 | + g726 = new G726_24(); | |
| 53 | + } | |
| 54 | + else if (rateBit == G726_BIT_RATE_16000) { | |
| 55 | + g726 = new G726_16(); | |
| 56 | + } | |
| 57 | + else { | |
| 58 | + return null; | |
| 59 | + } | |
| 60 | + | |
| 61 | + int pcmSize = point * CHANNEL * 2; | |
| 62 | + byte[] pcm = new byte[pcmSize]; | |
| 63 | + | |
| 64 | + int ret = g726.decode(data,pos,length,G726.AUDIO_ENCODING_LINEAR,pcm,0); | |
| 65 | + if (ret < 0) { | |
| 66 | + return null; | |
| 67 | + } | |
| 68 | + return pcm; | |
| 69 | + } | |
| 70 | + | |
| 71 | + @Override | |
| 72 | + public byte[] fromPCM(byte[] data) { | |
| 73 | + // TODO: | |
| 74 | + return new byte[0]; | |
| 75 | + } | |
| 76 | + | |
| 77 | + private static void readWrite(String in,String out,int size) throws Exception { | |
| 78 | + FileInputStream f = new FileInputStream(in); | |
| 79 | + FileOutputStream o = new FileOutputStream(out); | |
| 80 | + int len = -1; | |
| 81 | + byte[] buff = new byte[size]; | |
| 82 | + G726Codec g726Codec = new G726Codec(); | |
| 83 | + int index = 0; | |
| 84 | + while ((len = f.read(buff,index,buff.length)) > -1) { | |
| 85 | + o.write(g726Codec.toPCM(buff)); | |
| 86 | + } | |
| 87 | + } | |
| 88 | + | |
| 89 | + // mac下在终端中输入 /Applications/VLC.app/Contents/MacOS/VLC --demux=rawaud --rawaud-channels 1 --rawaud-samplerate 8000 ${path} | |
| 90 | + // 修改${path} 的值为pcm路径,即可播放转码后的pcm文件 | |
| 91 | + public static void main(String[] args) throws Exception { | |
| 92 | + | |
| 93 | + readWrite(Thread.currentThread().getContextClassLoader().getResource("g726/in_40.g726").getPath(), | |
| 94 | + "/Users/tmyam/Downloads/out_40.pcm",200); | |
| 95 | + | |
| 96 | + | |
| 97 | + readWrite(Thread.currentThread().getContextClassLoader().getResource("g726/in_32.g726").getPath(), | |
| 98 | + "/Users/tmyam/Downloads/out_32.pcm",160); | |
| 99 | + | |
| 100 | + | |
| 101 | + readWrite(Thread.currentThread().getContextClassLoader().getResource("g726/in_24.g726").getPath(), | |
| 102 | + "/Users/tmyam/Downloads/out_24.pcm",120); | |
| 103 | + | |
| 104 | + | |
| 105 | + readWrite(Thread.currentThread().getContextClassLoader().getResource("g726/in_16.g726").getPath(), | |
| 106 | + "/Users/tmyam/Downloads/out_16.pcm",80); | |
| 107 | + } | |
| 108 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/MP3Encoder.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/MP3Encoder.java | |
| 1 | +package cn.org.hentai.jtt1078.codec; | |
| 2 | + | |
| 3 | +import de.sciss.jump3r.lowlevel.LameEncoder; | |
| 4 | +import de.sciss.jump3r.mp3.Lame; | |
| 5 | + | |
| 6 | +import javax.sound.sampled.AudioFormat; | |
| 7 | +import java.io.ByteArrayOutputStream; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by matrixy on 2020/4/27. | |
| 11 | + */ | |
| 12 | +public class MP3Encoder | |
| 13 | +{ | |
| 14 | + static final AudioFormat PCM_FORMAT = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000, 16, 1, 1 * 2, -1, false); | |
| 15 | + | |
| 16 | + byte[] buffer = null; | |
| 17 | + ByteArrayOutputStream mp3Data; | |
| 18 | + LameEncoder encoder = null; | |
| 19 | + | |
| 20 | + public MP3Encoder() | |
| 21 | + { | |
| 22 | + encoder = new LameEncoder(PCM_FORMAT, 256, 3, Lame.MEDIUM, false); | |
| 23 | + buffer = new byte[encoder.getPCMBufferSize()]; | |
| 24 | + mp3Data = new ByteArrayOutputStream(encoder.getOutputBufferSize()); | |
| 25 | + } | |
| 26 | + | |
| 27 | + public byte[] encode(byte[] pcm) | |
| 28 | + { | |
| 29 | + if (pcm == null) return null; | |
| 30 | + int bytesToTransfer = Math.min(encoder.getPCMBufferSize(), pcm.length); | |
| 31 | + int bytesWritten; | |
| 32 | + int currentPcmPosition = 0; | |
| 33 | + | |
| 34 | + mp3Data.reset(); | |
| 35 | + | |
| 36 | + while (0 < (bytesWritten = encoder.encodeBuffer(pcm, currentPcmPosition, bytesToTransfer, buffer))) | |
| 37 | + { | |
| 38 | + currentPcmPosition += bytesToTransfer; | |
| 39 | + bytesToTransfer = Math.min(buffer.length, pcm.length - currentPcmPosition); | |
| 40 | + | |
| 41 | + mp3Data.write(buffer, 0, bytesWritten); | |
| 42 | + } | |
| 43 | + | |
| 44 | + return mp3Data.toByteArray(); | |
| 45 | + } | |
| 46 | + | |
| 47 | + public void close() | |
| 48 | + { | |
| 49 | + encoder.close(); | |
| 50 | + } | |
| 51 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/SilenceCodec.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/SilenceCodec.java | |
| 1 | +package cn.org.hentai.jtt1078.codec; | |
| 2 | + | |
| 3 | +import java.util.Arrays; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Created by houcheng on 2019-12-11. | |
| 7 | + */ | |
| 8 | +public class SilenceCodec extends AudioCodec | |
| 9 | +{ | |
| 10 | + static final byte[] BLANK = new byte[0]; | |
| 11 | + | |
| 12 | + @Override | |
| 13 | + public byte[] toPCM(byte[] data) | |
| 14 | + { | |
| 15 | + return BLANK; | |
| 16 | + } | |
| 17 | + | |
| 18 | + @Override | |
| 19 | + public byte[] fromPCM(byte[] data) | |
| 20 | + { | |
| 21 | + return BLANK; | |
| 22 | + } | |
| 23 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/g726/G726.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/g726/G726.java | |
| 1 | + | |
| 2 | +package cn.org.hentai.jtt1078.codec.g726; | |
| 3 | + | |
| 4 | + | |
| 5 | +import cn.org.hentai.jtt1078.codec.G711Codec; | |
| 6 | +import cn.org.hentai.jtt1078.codec.G711UCodec; | |
| 7 | + | |
| 8 | +/** Common routines for G.721 and G.723 conversions. | |
| 9 | + * <p> | |
| 10 | + * This implementation is based on the ANSI-C language reference implementations | |
| 11 | + * of the CCITT (International Telegraph and Telephone Consultative Committee) | |
| 12 | + * G.711, G.721 and G.723 voice compressions, provided by Sun Microsystems, Inc. | |
| 13 | + * <p> | |
| 14 | + * Acknowledgement to Sun Microsystems, Inc. for having released the original | |
| 15 | + * ANSI-C source code to the public domain. | |
| 16 | + */ | |
| 17 | +public abstract class G726 { | |
| 18 | + | |
| 19 | + // ##### C-to-Java conversion: ##### | |
| 20 | + // short becomes int | |
| 21 | + // char becomes int | |
| 22 | + // unsigned char becomes int | |
| 23 | + | |
| 24 | + | |
| 25 | + // *************************** STATIC *************************** | |
| 26 | + | |
| 27 | + /** ISDN u-law */ | |
| 28 | + public static final int AUDIO_ENCODING_ULAW=1; | |
| 29 | + | |
| 30 | + /** ISDN A-law */ | |
| 31 | + public static final int AUDIO_ENCODING_ALAW=2; | |
| 32 | + | |
| 33 | + /** PCM 2's-complement (0-center) */ | |
| 34 | + public static final int AUDIO_ENCODING_LINEAR=3; | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + /** The first 15 values, powers of 2. */ | |
| 39 | + private static final /*short*/int[] power2 = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000 }; | |
| 40 | + | |
| 41 | + | |
| 42 | + /** Quantizes the input val against the table of size short integers. | |
| 43 | + * It returns i if table[i-1]<=val<table[i]. | |
| 44 | + * <p> | |
| 45 | + * Using linear search for simple coding. */ | |
| 46 | + private static int quan(int val, /*short*/int[] table, int size) { | |
| 47 | + | |
| 48 | + int i; | |
| 49 | + for (i=0; i<size; i++) if (val<table[i]) break; | |
| 50 | + return i; | |
| 51 | + } | |
| 52 | + | |
| 53 | + | |
| 54 | + /** Given a raw sample, 'd', of the difference signal and a | |
| 55 | + * quantization step size scale factor, 'y', this routine returns the | |
| 56 | + * ADPCM codeword to which that sample gets quantized. The step | |
| 57 | + * size scale factor division operation is done in the log base 2 domain | |
| 58 | + * as a subtraction. | |
| 59 | + * <br> | |
| 60 | + * @param d - Raw difference signal sample | |
| 61 | + * @param y - Step size multiplier | |
| 62 | + * @param table - Quantization table | |
| 63 | + * @param size - Table size of short integers | |
| 64 | + */ | |
| 65 | + protected static int quantize(int d, int y, /*short*/int[] table, int size) { | |
| 66 | + | |
| 67 | + /* LOG | |
| 68 | + * Compute base 2 log of 'd', and store in 'dl'. | |
| 69 | + */ | |
| 70 | + /*short*/int dqm=Math.abs(d); /* Magnitude of 'd' */ | |
| 71 | + | |
| 72 | + /*short*/int exp=quan(dqm>>1, power2, 15); /* Integer part of base 2 log of 'd' */ | |
| 73 | + | |
| 74 | + /*short*/int mant=((dqm<<7)>>exp)&0x7F; /* Fractional part of base 2 log */ | |
| 75 | + | |
| 76 | + /*short*/int dl=(exp<<7)+mant; /* Log of magnitude of 'd' */ | |
| 77 | + | |
| 78 | + /* SUBTB | |
| 79 | + * "Divide" by step size multiplier. | |
| 80 | + */ | |
| 81 | + /* Step size scale factor normalized log */ | |
| 82 | + /*short*/int dln=dl-(y>>2); | |
| 83 | + | |
| 84 | + /* QUAN | |
| 85 | + * Obtain codword i for 'd'. | |
| 86 | + */ | |
| 87 | + int i=quan(dln, table, size); | |
| 88 | + if (d<0) /* take 1's complement of i */ | |
| 89 | + return ((size<<1)+1-i); | |
| 90 | + else if (i==0) /* take 1's complement of 0 */ | |
| 91 | + return ((size<<1)+1); /* new in 1988 */ | |
| 92 | + else | |
| 93 | + return (i); | |
| 94 | + } | |
| 95 | + | |
| 96 | + | |
| 97 | + /** Returns reconstructed difference signal 'dq' obtained from | |
| 98 | + * codeword 'i' and quantization step size scale factor 'y'. | |
| 99 | + * Multiplication is performed in log base 2 domain as addition. | |
| 100 | + * @param sign - 0 for non-negative value | |
| 101 | + * @param dqln - G.72x codeword | |
| 102 | + * @param y - Step size multiplier | |
| 103 | + */ | |
| 104 | + protected static int reconstruct(int sign, int dqln, int y) { | |
| 105 | + | |
| 106 | + /* Log of 'dq' magnitude */ | |
| 107 | + /*short*/int dql=dqln+(y>>2); /* ADDA */ | |
| 108 | + | |
| 109 | + if (dql<0) { | |
| 110 | + return ((sign!=0)? -0x8000 : 0); | |
| 111 | + } | |
| 112 | + else { | |
| 113 | + /* ANTILOG */ | |
| 114 | + /* Integer part of log */ | |
| 115 | + /*short*/int dex=(dql>>7)&15; | |
| 116 | + /*short*/int dqt=128+(dql&127); | |
| 117 | + /* Reconstructed difference signal sample */ | |
| 118 | + /*short*/int dq=(dqt<<7)>>(14-dex); | |
| 119 | + return ((sign!=0)? (dq-0x8000) : dq); | |
| 120 | + } | |
| 121 | + } | |
| 122 | + | |
| 123 | + | |
| 124 | + /** updates the state variables for each output code | |
| 125 | + * @param code_size - distinguish 723_40 with others | |
| 126 | + * @param y - quantizer step size | |
| 127 | + * @param wi - scale factor multiplier | |
| 128 | + * @param fi - for long/short term energies | |
| 129 | + * @param dq - quantized prediction difference | |
| 130 | + * @param sr - reconstructed signal | |
| 131 | + * @param dqsez - difference from 2-pole predictor | |
| 132 | + * @param state - coder state | |
| 133 | + */ | |
| 134 | + protected static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, G726State state) { | |
| 135 | + | |
| 136 | + int cnt; | |
| 137 | + /*short*/int mag, exp, mant; /* Adaptive predictor, FLOAT A */ | |
| 138 | + /*short*/int a2p; /* LIMC */ | |
| 139 | + /*short*/int a1ul; /* UPA1 */ | |
| 140 | + /*short*/int ua2, pks1; /* UPA2 */ | |
| 141 | + /*short*/int uga2a, fa1; | |
| 142 | + /*short*/int uga2b; | |
| 143 | + /*char*/int tr; /* tone/transition detector */ | |
| 144 | + /*short*/int ylint, thr2, dqthr; | |
| 145 | + /*short*/int ylfrac, thr1; | |
| 146 | + /*short*/int pk0; | |
| 147 | + | |
| 148 | + // ##### C-to-Java conversion: ##### | |
| 149 | + // init a2p | |
| 150 | + a2p=0; | |
| 151 | + | |
| 152 | + pk0=(dqsez<0)? 1 : 0; /* needed in updating predictor poles */ | |
| 153 | + | |
| 154 | + mag=dq&0x7FFF; /* prediction difference magnitude */ | |
| 155 | + /* TRANS */ | |
| 156 | + ylint=state.yl>>15; /* exponent part of yl */ | |
| 157 | + ylfrac=(state.yl>>10)&0x1F; /* fractional part of yl */ | |
| 158 | + thr1=(32+ylfrac)<<ylint; /* threshold */ | |
| 159 | + thr2=(ylint>9)? 31<<10 : thr1; /* limit thr2 to 31<<10 */ | |
| 160 | + dqthr=(thr2+(thr2>>1))>>1; /* dqthr=0.75 * thr2 */ | |
| 161 | + if (state.td==0) /* signal supposed voice */ | |
| 162 | + tr=0; | |
| 163 | + else | |
| 164 | + if (mag<=dqthr) /* supposed data, but small mag */ | |
| 165 | + tr=0; /* treated as voice */ | |
| 166 | + else /* signal is data (modem) */ | |
| 167 | + tr=1; | |
| 168 | + | |
| 169 | + /* Quantizer scale factor adaptation. */ | |
| 170 | + | |
| 171 | + /* FUNCTW&FILTD&DELAY */ | |
| 172 | + /* update non-steady state step size multiplier */ | |
| 173 | + state.yu=y+((wi-y)>>5); | |
| 174 | + | |
| 175 | + /* LIMB */ | |
| 176 | + if (state.yu<544) /* 544<=yu<=5120 */ | |
| 177 | + state.yu=544; | |
| 178 | + else | |
| 179 | + if (state.yu>5120) | |
| 180 | + state.yu=5120; | |
| 181 | + | |
| 182 | + /* FILTE&DELAY */ | |
| 183 | + /* update steady state step size multiplier */ | |
| 184 | + state.yl+=state.yu+((-state.yl)>>6); | |
| 185 | + | |
| 186 | + /* | |
| 187 | + * Adaptive predictor coefficients. | |
| 188 | + */ | |
| 189 | + if (tr==1) { | |
| 190 | + /* reset a's and b's for modem signal */ | |
| 191 | + state.a[0]=0; | |
| 192 | + state.a[1]=0; | |
| 193 | + state.b[0]=0; | |
| 194 | + state.b[1]=0; | |
| 195 | + state.b[2]=0; | |
| 196 | + state.b[3]=0; | |
| 197 | + state.b[4]=0; | |
| 198 | + state.b[5]=0; | |
| 199 | + } | |
| 200 | + else { | |
| 201 | + /* update a's and b's */ | |
| 202 | + pks1=pk0^state.pk[0]; /* UPA2 */ | |
| 203 | + | |
| 204 | + /* update predictor pole a[1] */ | |
| 205 | + a2p=state.a[1]-(state.a[1]>>7); | |
| 206 | + if (dqsez != 0) { | |
| 207 | + fa1=(pks1!=0)? state.a[0] : -state.a[0]; | |
| 208 | + if (fa1<-8191) /* a2p=function of fa1 */ | |
| 209 | + a2p-=0x100; | |
| 210 | + else | |
| 211 | + if (fa1>8191) | |
| 212 | + a2p+=0xFF; | |
| 213 | + else | |
| 214 | + a2p+=fa1>>5; | |
| 215 | + | |
| 216 | + if ((pk0^state.pk[1])!=0) { | |
| 217 | + /* LIMC */ | |
| 218 | + if (a2p<=-12160) | |
| 219 | + a2p=-12288; | |
| 220 | + else | |
| 221 | + if (a2p>=12416) | |
| 222 | + a2p=12288; | |
| 223 | + else | |
| 224 | + a2p-=0x80; | |
| 225 | + } | |
| 226 | + else | |
| 227 | + if (a2p<=-12416) | |
| 228 | + a2p=-12288; | |
| 229 | + else | |
| 230 | + if (a2p>=12160) | |
| 231 | + a2p=12288; | |
| 232 | + else | |
| 233 | + a2p+=0x80; | |
| 234 | + } | |
| 235 | + | |
| 236 | + /* TRIGB&DELAY */ | |
| 237 | + state.a[1]=a2p; | |
| 238 | + | |
| 239 | + /* UPA1 */ | |
| 240 | + /* update predictor pole a[0] */ | |
| 241 | + state.a[0] -= state.a[0]>>8; | |
| 242 | + if (dqsez != 0) | |
| 243 | + if (pks1==0) | |
| 244 | + state.a[0]+=192; | |
| 245 | + else | |
| 246 | + state.a[0] -= 192; | |
| 247 | + | |
| 248 | + /* LIMD */ | |
| 249 | + a1ul=15360-a2p; | |
| 250 | + if (state.a[0]<-a1ul) | |
| 251 | + state.a[0]=-a1ul; | |
| 252 | + else if (state.a[0]>a1ul) | |
| 253 | + state.a[0]=a1ul; | |
| 254 | + | |
| 255 | + /* UPB : update predictor zeros b[6] */ | |
| 256 | + for (cnt=0; cnt<6; cnt++) { | |
| 257 | + | |
| 258 | + if (code_size==5) /* for 40Kbps G.723 */ | |
| 259 | + state.b[cnt]-=state.b[cnt]>>9; | |
| 260 | + else /* for G.721 and 24Kbps G.723 */ | |
| 261 | + state.b[cnt]-=state.b[cnt]>>8; | |
| 262 | + if ((dq&0x7FFF)!=0) { | |
| 263 | + /* XOR */ | |
| 264 | + if ((dq^state.dq[cnt])>=0) | |
| 265 | + state.b[cnt]+=128; | |
| 266 | + else | |
| 267 | + state.b[cnt]-=128; | |
| 268 | + } | |
| 269 | + } | |
| 270 | + } | |
| 271 | + | |
| 272 | + for (cnt=5; cnt>0; cnt--) state.dq[cnt]=state.dq[cnt-1]; | |
| 273 | + /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ | |
| 274 | + if (mag==0) { | |
| 275 | + state.dq[0]=(dq>=0)? 0x20 : 0xFC20; | |
| 276 | + } | |
| 277 | + else { | |
| 278 | + exp=quan(mag, power2, 15); | |
| 279 | + state.dq[0]=(dq>=0) ? (exp<<6)+((mag<<6)>>exp) : (exp<<6)+((mag<<6)>>exp)-0x400; | |
| 280 | + } | |
| 281 | + | |
| 282 | + state.sr[1]=state.sr[0]; | |
| 283 | + /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ | |
| 284 | + if (sr==0) { | |
| 285 | + state.sr[0]=0x20; | |
| 286 | + } | |
| 287 | + else | |
| 288 | + if (sr>0) { | |
| 289 | + exp=quan(sr, power2, 15); | |
| 290 | + state.sr[0]=(exp<<6)+((sr<<6)>>exp); | |
| 291 | + } | |
| 292 | + else | |
| 293 | + if (sr>-32768) { | |
| 294 | + mag=-sr; | |
| 295 | + exp=quan(mag, power2, 15); | |
| 296 | + state.sr[0]=(exp<<6)+((mag<<6)>>exp)-0x400; | |
| 297 | + } | |
| 298 | + else | |
| 299 | + state.sr[0]=0xFC20; | |
| 300 | + | |
| 301 | + /* DELAY A */ | |
| 302 | + state.pk[1]=state.pk[0]; | |
| 303 | + state.pk[0]=pk0; | |
| 304 | + | |
| 305 | + /* TONE */ | |
| 306 | + if (tr==1) /* this sample has been treated as data */ | |
| 307 | + state.td=0; /* next one will be treated as voice */ | |
| 308 | + else | |
| 309 | + if (a2p<-11776) /* small sample-to-sample correlation */ | |
| 310 | + state.td=1; /* signal may be data */ | |
| 311 | + else /* signal is voice */ | |
| 312 | + state.td=0; | |
| 313 | + | |
| 314 | + /* | |
| 315 | + * Adaptation speed control. | |
| 316 | + */ | |
| 317 | + state.dms+=(fi-state.dms)>>5; /* FILTA */ | |
| 318 | + state.dml+=(((fi<<2)-state.dml)>>7); /* FILTB */ | |
| 319 | + | |
| 320 | + if (tr==1) | |
| 321 | + state.ap=256; | |
| 322 | + else | |
| 323 | + if (y<1536) /* SUBTC */ | |
| 324 | + state.ap+=(0x200-state.ap)>>4; | |
| 325 | + else | |
| 326 | + if (state.td==1) | |
| 327 | + state.ap+=(0x200-state.ap)>>4; | |
| 328 | + else | |
| 329 | + if (Math.abs((state.dms<<2)-state.dml)>=(state.dml>>3)) | |
| 330 | + state.ap+=(0x200-state.ap)>>4; | |
| 331 | + else | |
| 332 | + state.ap+=(-state.ap)>>4; | |
| 333 | + } | |
| 334 | + | |
| 335 | + /** At the end of ADPCM decoding, it simulates an encoder which may be receiving | |
| 336 | + * the output of this decoder as a tandem process. If the output of the | |
| 337 | + * simulated encoder differs from the input to this decoder, the decoder output | |
| 338 | + * is adjusted by one level of A-law or u-law codes. | |
| 339 | + * | |
| 340 | + * @param sr - decoder output linear PCM sample, | |
| 341 | + * @param se - predictor estimate sample, | |
| 342 | + * @param y - quantizer step size, | |
| 343 | + * @param i - decoder input code, | |
| 344 | + * @param sign - sign bit of code i | |
| 345 | + * | |
| 346 | + * @return adjusted A-law or u-law compressed sample. | |
| 347 | + */ | |
| 348 | + protected static int tandem_adjust_alaw(int sr, int se, int y, int i, int sign, /*short*/int[] qtab) { | |
| 349 | + | |
| 350 | + /*unsigned char*/int sp; /* A-law compressed 8-bit code */ | |
| 351 | + /*short*/int dx; /* prediction error */ | |
| 352 | + /*char*/int id; /* quantized prediction error */ | |
| 353 | + int sd; /* adjusted A-law decoded sample value */ | |
| 354 | + int im; /* biased magnitude of i */ | |
| 355 | + int imx; /* biased magnitude of id */ | |
| 356 | + | |
| 357 | + if (sr<=-32768) sr=-1; | |
| 358 | + sp= G711Codec.linear2alaw((short)((sr>>1)<<3)); /* short to A-law compression */ | |
| 359 | + dx=(G711Codec.alaw2linear((byte)sp)>>2)-se; /* 16-bit prediction error */ | |
| 360 | + id=quantize(dx, y, qtab, sign-1); | |
| 361 | + | |
| 362 | + if (id==i) { | |
| 363 | + /* no adjustment on sp */ | |
| 364 | + return (sp); | |
| 365 | + } | |
| 366 | + else { | |
| 367 | + /* sp adjustment needed */ | |
| 368 | + /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ | |
| 369 | + im=i^sign; /* 2's complement to biased unsigned */ | |
| 370 | + imx=id^sign; | |
| 371 | + | |
| 372 | + if (imx>im) { | |
| 373 | + /* sp adjusted to next lower value */ | |
| 374 | + if ((sp&0x80)!=0) { | |
| 375 | + sd=(sp==0xD5)? 0x55 : ((sp^0x55)-1)^0x55; | |
| 376 | + } | |
| 377 | + else { | |
| 378 | + sd=(sp==0x2A)? 0x2A : ((sp^0x55)+1)^0x55; | |
| 379 | + } | |
| 380 | + } | |
| 381 | + else { | |
| 382 | + /* sp adjusted to next higher value */ | |
| 383 | + if ((sp&0x80)!=0) | |
| 384 | + sd=(sp==0xAA)? 0xAA : ((sp^0x55)+1)^0x55; | |
| 385 | + else | |
| 386 | + sd=(sp==0x55)? 0xD5 : ((sp^0x55)-1)^0x55; | |
| 387 | + } | |
| 388 | + return (sd); | |
| 389 | + } | |
| 390 | + } | |
| 391 | + | |
| 392 | + /** @param sr - decoder output linear PCM sample | |
| 393 | + * @param se - predictor estimate sample | |
| 394 | + * @param y - quantizer step size | |
| 395 | + * @param i - decoder input code | |
| 396 | + * @param sign | |
| 397 | + * @param qtab | |
| 398 | + */ | |
| 399 | + protected static int tandem_adjust_ulaw(int sr, int se, int y, int i, int sign, /*short*/int[] qtab) { | |
| 400 | + | |
| 401 | + /*unsigned char*/int sp; /* u-law compressed 8-bit code */ | |
| 402 | + /*short*/int dx; /* prediction error */ | |
| 403 | + /*char*/int id; /* quantized prediction error */ | |
| 404 | + int sd; /* adjusted u-law decoded sample value */ | |
| 405 | + int im; /* biased magnitude of i */ | |
| 406 | + int imx; /* biased magnitude of id */ | |
| 407 | + | |
| 408 | + if (sr<=-32768) sr=0; | |
| 409 | + sp= G711UCodec.linear2ulaw((short)(sr<<2)); /* short to u-law compression */ | |
| 410 | + dx=(G711UCodec.ulaw2linear((byte)sp)>>2)-se; /* 16-bit prediction error */ | |
| 411 | + id=quantize(dx, y, qtab, sign-1); | |
| 412 | + if (id==i) { | |
| 413 | + return (sp); | |
| 414 | + } | |
| 415 | + else { | |
| 416 | + /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ | |
| 417 | + im=i^sign; /* 2's complement to biased unsigned */ | |
| 418 | + imx=id^sign; | |
| 419 | + if (imx>im) { | |
| 420 | + /* sp adjusted to next lower value */ | |
| 421 | + if ((sp&0x80)!=0) | |
| 422 | + sd=(sp==0xFF)? 0x7E : sp+1; | |
| 423 | + else | |
| 424 | + sd=(sp==0)? 0 : sp-1; | |
| 425 | + | |
| 426 | + } | |
| 427 | + else { | |
| 428 | + /* sp adjusted to next higher value */ | |
| 429 | + if ((sp&0x80)!=0) | |
| 430 | + sd=(sp==0x80)? 0x80 : sp-1; | |
| 431 | + else | |
| 432 | + sd=(sp==0x7F)? 0xFE : sp+1; | |
| 433 | + } | |
| 434 | + return (sd); | |
| 435 | + } | |
| 436 | + } | |
| 437 | + | |
| 438 | + | |
| 439 | + // ##### C-to-Java conversion: ##### | |
| 440 | + | |
| 441 | + /** Converts a byte into an unsigned int. */ | |
| 442 | + protected static int unsignedInt(byte b) { | |
| 443 | + return ((int)b+0x100)&0xFF; | |
| 444 | + } | |
| 445 | + | |
| 446 | + // ##### 2 bytes to int conversion: ##### | |
| 447 | + | |
| 448 | + /** Converts 2 little-endian-bytes into an unsigned int. */ | |
| 449 | + public static int unsignedIntLittleEndian(byte hi_b, byte lo_b) { | |
| 450 | + return (unsignedInt(hi_b)<<8) + unsignedInt(lo_b); | |
| 451 | + } | |
| 452 | + | |
| 453 | + /** Converts 2 little-endian-bytes into a signed int. */ | |
| 454 | + public static int signedIntLittleEndian(byte hi_b, byte lo_b) { | |
| 455 | + int sign_bit=hi_b>>7; | |
| 456 | + return (sign_bit==0)? (unsignedInt(hi_b)<<8) + unsignedInt(lo_b) : (-1^0x7FFF)^(((unsignedInt(hi_b)&0x7F)<<8) + unsignedInt(lo_b)); | |
| 457 | + } | |
| 458 | + | |
| 459 | + | |
| 460 | + // ************************* NON-STATIC ************************* | |
| 461 | + | |
| 462 | + /** Encoding state */ | |
| 463 | + G726State state; | |
| 464 | + | |
| 465 | + int type; | |
| 466 | + | |
| 467 | + /** Creates a new G726 processor, that can be used to encode from or decode do PCM audio data. */ | |
| 468 | + public G726(int type) { | |
| 469 | + this.type = type; | |
| 470 | + state=new G726State(); | |
| 471 | + } | |
| 472 | + | |
| 473 | + public int getType() { | |
| 474 | + return type; | |
| 475 | + } | |
| 476 | + | |
| 477 | + /** Encodes the input vale of linear PCM, A-law or u-law data sl and returns | |
| 478 | + * the resulting code. -1 is returned for unknown input coding value. */ | |
| 479 | + public abstract int encode(int sl, int in_coding); | |
| 480 | + | |
| 481 | + | |
| 482 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 483 | + * the G726 encoded chuck into out_buff. <br> | |
| 484 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 485 | + * in_coding value. */ | |
| 486 | + public abstract int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset); | |
| 487 | + | |
| 488 | + | |
| 489 | + /** Decodes a 4-bit code of G.72x encoded data of i and | |
| 490 | + * returns the resulting linear PCM, A-law or u-law value. | |
| 491 | + * return -1 for unknown out_coding value. */ | |
| 492 | + public abstract int decode(int i, int out_coding); | |
| 493 | + | |
| 494 | + | |
| 495 | + /** Decodes the input chunk in_buff of G726 encoded data and returns | |
| 496 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 497 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 498 | + * out_coding value. */ | |
| 499 | + public abstract int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset); | |
| 500 | + | |
| 501 | +} | |
| 0 | 502 | \ No newline at end of file | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/g726/G726State.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/g726/G726State.java | |
| 1 | +package cn.org.hentai.jtt1078.codec.g726; | |
| 2 | + | |
| 3 | +public class G726State { | |
| 4 | + | |
| 5 | + /** Locked or steady state step size multiplier. */ | |
| 6 | + /*long*/int yl; | |
| 7 | + /** Unlocked or non-steady state step size multiplier. */ | |
| 8 | + /*short*/int yu; | |
| 9 | + /** Short term energy estimate. */ | |
| 10 | + /*short*/int dms; | |
| 11 | + /** Long term energy estimate. */ | |
| 12 | + /*short*/int dml; | |
| 13 | + /** Linear weighting coefficient of 'yl' and 'yu'. */ | |
| 14 | + /*short*/int ap; | |
| 15 | + | |
| 16 | + /** Coefficients of pole portion of prediction filter. */ | |
| 17 | + /*short*/int[] a; | |
| 18 | + /** Coefficients of zero portion of prediction filter. */ | |
| 19 | + /*short*/int[] b; | |
| 20 | + /** Signs of previous two samples of a partially | |
| 21 | + * reconstructed signal. */ | |
| 22 | + /*short*/int[] pk; | |
| 23 | + /** Previous 6 samples of the quantized difference | |
| 24 | + * signal represented in an internal floating point | |
| 25 | + * format. */ | |
| 26 | + /*short*/int[] dq; | |
| 27 | + /** Previous 2 samples of the quantized difference | |
| 28 | + * signal represented in an internal floating point | |
| 29 | + * format. */ | |
| 30 | + /*short*/int[] sr; | |
| 31 | + /* delayed tone detect, new in 1988 version */ | |
| 32 | + /*char*/int td; | |
| 33 | + | |
| 34 | + | |
| 35 | + /** The first 15 values, powers of 2. */ | |
| 36 | + private static final /*short*/int[] power2 = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000 }; | |
| 37 | + | |
| 38 | + | |
| 39 | + /** Quantizes the input val against the table of size short integers. | |
| 40 | + * It returns i if table[i-1]<=val<table[i]. | |
| 41 | + * <p> | |
| 42 | + * Using linear search for simple coding. */ | |
| 43 | + private static int quan(int val, /*short*/int[] table, int size) { | |
| 44 | + | |
| 45 | + int i; | |
| 46 | + for (i=0; i<size; i++) if (val<table[i]) break; | |
| 47 | + return i; | |
| 48 | + } | |
| 49 | + | |
| 50 | + | |
| 51 | + /** returns the integer product of the 14-bit integer "an" and | |
| 52 | + * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". */ | |
| 53 | + private static int fmult(int an, int srn) { | |
| 54 | + | |
| 55 | + /*short*/int anmag=(an>0)? an : ((-an)&0x1FFF); | |
| 56 | + /*short*/int anexp=quan(anmag, power2, 15)-6; | |
| 57 | + /*short*/int anmant=(anmag==0)? 32 : | |
| 58 | + (anexp >= 0)? anmag>>anexp : anmag<<-anexp; | |
| 59 | + /*short*/int wanexp=anexp + ((srn>>6)&0xF) - 13; | |
| 60 | + | |
| 61 | + /*short*/int wanmant=(anmant*(srn&077) + 0x30)>>4; | |
| 62 | + /*short*/int retval=(wanexp>=0)? ((wanmant<<wanexp)&0x7FFF) : (wanmant>>-wanexp); | |
| 63 | + | |
| 64 | + return (((an^srn)<0)? -retval : retval); | |
| 65 | + } | |
| 66 | + | |
| 67 | + | |
| 68 | + /** Creates a new G726State. */ | |
| 69 | + public G726State() { | |
| 70 | + a=new /*short*/int[2]; | |
| 71 | + b=new /*short*/int[6]; | |
| 72 | + pk=new /*short*/int[2]; | |
| 73 | + dq=new /*short*/int[6]; | |
| 74 | + sr=new /*short*/int[2]; | |
| 75 | + init(); | |
| 76 | + } | |
| 77 | + | |
| 78 | + /** This routine initializes and/or resets the G726State 'state'. <br> | |
| 79 | + * All the initial state values are specified in the CCITT G.721 document. */ | |
| 80 | + private void init() { | |
| 81 | + yl=34816; | |
| 82 | + yu=544; | |
| 83 | + dms=0; | |
| 84 | + dml=0; | |
| 85 | + ap=0; | |
| 86 | + for (int cnta=0; cnta<2; cnta++) { | |
| 87 | + a[cnta]=0; | |
| 88 | + pk[cnta]=0; | |
| 89 | + sr[cnta]=32; | |
| 90 | + } | |
| 91 | + for (int cnta=0; cnta<6; cnta++) { | |
| 92 | + b[cnta]=0; | |
| 93 | + dq[cnta]=32; | |
| 94 | + } | |
| 95 | + td=0; | |
| 96 | + } | |
| 97 | + | |
| 98 | + /** computes the estimated signal from 6-zero predictor. */ | |
| 99 | + public int predictor_zero() { | |
| 100 | + | |
| 101 | + int sezi=fmult(b[0]>>2, dq[0]); | |
| 102 | + /* ACCUM */ | |
| 103 | + for (int i=1; i<6; i++) sezi+=fmult(b[i]>>2,dq[i]); | |
| 104 | + return sezi; | |
| 105 | + } | |
| 106 | + | |
| 107 | + | |
| 108 | + /** computes the estimated signal from 2-pole predictor. */ | |
| 109 | + public int predictor_pole() { | |
| 110 | + | |
| 111 | + return (fmult(a[1]>>2,sr[1]) + fmult(a[0]>>2,sr[0])); | |
| 112 | + } | |
| 113 | + | |
| 114 | + | |
| 115 | + /** computes the quantization step size of the adaptive quantizer. */ | |
| 116 | + public int step_size() { | |
| 117 | + | |
| 118 | + if (ap>=256) return (yu); | |
| 119 | + else { | |
| 120 | + int y=yl>>6; | |
| 121 | + int dif=yu-y; | |
| 122 | + int al=ap>>2; | |
| 123 | + if (dif>0) y+=(dif * al)>>6; | |
| 124 | + else | |
| 125 | + if (dif<0) y+=(dif * al+0x3F)>>6; | |
| 126 | + return y; | |
| 127 | + } | |
| 128 | + } | |
| 129 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/g726/G726_16.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/g726/G726_16.java | |
| 1 | +package cn.org.hentai.jtt1078.codec.g726; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.G711Codec; | |
| 4 | +import cn.org.hentai.jtt1078.codec.G711UCodec; | |
| 5 | + | |
| 6 | +/** G726_16 encoder and decoder. | |
| 7 | + * <p> | |
| 8 | + * These routines comprise an implementation of the CCITT G.726 16kbps | |
| 9 | + * ADPCM coding algorithm. Essentially, this implementation is identical to | |
| 10 | + * the bit level description except for a few deviations which | |
| 11 | + * take advantage of workstation attributes, such as hardware 2's | |
| 12 | + * complement arithmetic. | |
| 13 | + * <p> | |
| 14 | + * The deviation from the bit level specification (lookup tables), | |
| 15 | + * preserves the bit level performance specifications. | |
| 16 | + * <p> | |
| 17 | + * As outlined in the G.723 Recommendation, the algorithm is broken | |
| 18 | + * down into modules. Each section of code below is preceded by | |
| 19 | + * the name of the module which it is implementing. | |
| 20 | + * <p> | |
| 21 | + * This implementation is based on the ANSI-C language reference implementations | |
| 22 | + * of the CCITT (International Telegraph and Telephone Consultative Committee) | |
| 23 | + * G.711, G.721 and G.723 voice compressions, provided by Sun Microsystems, Inc. | |
| 24 | + * <p> | |
| 25 | + * Acknowledgement to Sun Microsystems, Inc. for having released the original | |
| 26 | + * ANSI-C source code to the public domain. | |
| 27 | + */ | |
| 28 | +public class G726_16 extends G726 { | |
| 29 | + | |
| 30 | + // ##### C-to-Java conversion: ##### | |
| 31 | + // short becomes int | |
| 32 | + // char becomes int | |
| 33 | + // unsigned char becomes int | |
| 34 | + | |
| 35 | + | |
| 36 | + // *************************** STATIC *************************** | |
| 37 | + | |
| 38 | + /* | |
| 39 | + * Maps G723_16 code word to ructeconstructed scale factor normalized log | |
| 40 | + * magnitude values. | |
| 41 | + */ | |
| 42 | + static /*short*/int[] _dqlntab={116, 365, 365, 116}; | |
| 43 | + | |
| 44 | + /* Maps G723_16 code word to log of scale factor multiplier. */ | |
| 45 | + static /*short*/int[] _witab={-704, 14048, 14048, -704}; | |
| 46 | + | |
| 47 | + /* | |
| 48 | + * Maps G723_16 code words to a set of values whose long and short | |
| 49 | + * term averages are computed and then compared to give an indication | |
| 50 | + * how stationary (steady state) the signal is. | |
| 51 | + */ | |
| 52 | + static /*short*/int[] _fitab={ 0x000, 0xE00, 0xE00, 0x000}; | |
| 53 | + | |
| 54 | + static /*short*/int[] qtab_723_16={261}; | |
| 55 | + | |
| 56 | + /** Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens | |
| 57 | + * the resulting 5-bit CCITT G726 16kbps code. | |
| 58 | + * Returns -1 if the input coding value is invalid. */ | |
| 59 | + public static int encode(int sl, int in_coding, G726State state) { | |
| 60 | + | |
| 61 | + /*short*/int sei, sezi, se, sez; /* ACCUM */ | |
| 62 | + /*short*/int d; /* SUBTA */ | |
| 63 | + /*short*/int y; /* MIX */ | |
| 64 | + /*short*/int sr; /* ADDB */ | |
| 65 | + /*short*/int dqsez; /* ADDC */ | |
| 66 | + /*short*/int dq, i; | |
| 67 | + | |
| 68 | + switch (in_coding) { | |
| 69 | + /* linearize input sample to 14-bit PCM */ | |
| 70 | + case AUDIO_ENCODING_ALAW: | |
| 71 | + sl= G711Codec.alaw2linear((byte) sl) >> 2; | |
| 72 | + break; | |
| 73 | + case AUDIO_ENCODING_ULAW: | |
| 74 | + sl= G711UCodec.ulaw2linear((byte)sl) >> 2; | |
| 75 | + break; | |
| 76 | + case AUDIO_ENCODING_LINEAR: | |
| 77 | + sl >>= 2; /* sl of 14-bit dynamic range */ | |
| 78 | + break; | |
| 79 | + default: | |
| 80 | + return (-1); | |
| 81 | + } | |
| 82 | + | |
| 83 | + sezi=state.predictor_zero(); | |
| 84 | + sez=sezi >> 1; | |
| 85 | + sei=sezi+state.predictor_pole(); | |
| 86 | + se=sei >> 1; /* se=estimated signal */ | |
| 87 | + | |
| 88 | + d=sl-se; /* d=estimation difference */ | |
| 89 | + | |
| 90 | + /* quantize prediction difference */ | |
| 91 | + y=state.step_size(); /* adaptive quantizer step size */ | |
| 92 | + i=quantize(d, y, qtab_723_16, 1); /* i=ADPCM code */ | |
| 93 | + | |
| 94 | + dq=reconstruct(i & 0x02, _dqlntab[i], y); /* quantized diff */ | |
| 95 | + | |
| 96 | + sr=(dq<0)? se-(dq & 0x3FFF) : se+dq; /* reconstructed signal */ | |
| 97 | + | |
| 98 | + dqsez=sr+sez-se; /* dqsez=pole prediction diff. */ | |
| 99 | + | |
| 100 | + update(2, y, _witab[i], _fitab[i], dq, sr, dqsez, state); | |
| 101 | + | |
| 102 | + return (i); | |
| 103 | + } | |
| 104 | + | |
| 105 | + | |
| 106 | + /** Decodes a 5-bit CCITT G.726 40kbps code and returns | |
| 107 | + * the resulting 16-bit linear PCM, A-law or u-law sample value. | |
| 108 | + * -1 is returned if the output coding is unknown. */ | |
| 109 | + public static int decode(int i, int out_coding, G726State state) { | |
| 110 | + | |
| 111 | + /*short*/int sezi, sei, sez, se; /* ACCUM */ | |
| 112 | + /*short*/int y, dif; /* MIX */ | |
| 113 | + /*short*/int sr; /* ADDB */ | |
| 114 | + /*short*/int dq; | |
| 115 | + /*short*/int dqsez; | |
| 116 | + | |
| 117 | + i &= 0x03; /* mask to get proper bits */ | |
| 118 | + sezi=state.predictor_zero(); | |
| 119 | + sez=sezi >> 1; | |
| 120 | + sei=sezi+state.predictor_pole(); | |
| 121 | + se=sei >> 1; /* se=estimated signal */ | |
| 122 | + | |
| 123 | + y=state.step_size(); /* adaptive quantizer step size */ | |
| 124 | + dq=reconstruct(i & 0x02, _dqlntab[i], y); /* estimation diff. */ | |
| 125 | + | |
| 126 | + sr=(dq<0)? (se-(dq & 0x3FFF)) : (se+dq); /* reconst. signal */ | |
| 127 | + | |
| 128 | + dqsez=sr-se+sez; /* pole prediction diff. */ | |
| 129 | + | |
| 130 | + update(2, y, _witab[i], _fitab[i], dq, sr, dqsez, state); | |
| 131 | + | |
| 132 | + switch (out_coding) { | |
| 133 | + | |
| 134 | + case AUDIO_ENCODING_ALAW: | |
| 135 | + return (tandem_adjust_alaw(sr, se, y, i, 0x02, qtab_723_16)); | |
| 136 | + case AUDIO_ENCODING_ULAW: | |
| 137 | + return (tandem_adjust_ulaw(sr, se, y, i, 0x02, qtab_723_16)); | |
| 138 | + case AUDIO_ENCODING_LINEAR: | |
| 139 | + return (sr << 2); /* sr was of 14-bit dynamic range */ | |
| 140 | + default: | |
| 141 | + return (-1); | |
| 142 | + } | |
| 143 | + } | |
| 144 | + | |
| 145 | + | |
| 146 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 147 | + * the G726_16 encoded chuck into out_buff. <br> | |
| 148 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 149 | + * in_coding value. */ | |
| 150 | + public static int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset, G726State state) { | |
| 151 | + | |
| 152 | + if (in_coding==AUDIO_ENCODING_ALAW || in_coding==AUDIO_ENCODING_ULAW) { | |
| 153 | + | |
| 154 | + int len_div_8=in_len/8; | |
| 155 | + for (int i=0; i<len_div_8; i++) { | |
| 156 | + long value8=0; | |
| 157 | + int in_index=in_offset+i*8; | |
| 158 | + for (int j=0; j<8; j++) { | |
| 159 | + int in_value=unsignedInt(in_buff[in_index+j]); | |
| 160 | + int out_value=encode(in_value,in_coding,state); | |
| 161 | + value8+=((long)out_value)<<(2*(7-j)); | |
| 162 | + } | |
| 163 | + int out_index=out_offset+i*2; | |
| 164 | + for (int k=0; k<2; k++) { | |
| 165 | + out_buff[out_index+k]=(byte)(value8>>(8*(1-k))); | |
| 166 | + } | |
| 167 | + } | |
| 168 | + return len_div_8*2; | |
| 169 | + } | |
| 170 | + else | |
| 171 | + if (in_coding==AUDIO_ENCODING_LINEAR) { | |
| 172 | + | |
| 173 | + int len_div_16=in_len/16; | |
| 174 | + for (int i=0; i<len_div_16; i++) { | |
| 175 | + long value16=0; | |
| 176 | + int in_index=in_offset+i*16; | |
| 177 | + for (int j=0; j<8; j++) { | |
| 178 | + int j2=j*2; | |
| 179 | + int in_value=signedIntLittleEndian(in_buff[in_index+j2+1],in_buff[in_index+j2]); | |
| 180 | + int out_value=encode(in_value,in_coding,state); | |
| 181 | + value16+=((long)out_value)<<(2*(7-j)); | |
| 182 | + } | |
| 183 | + int out_index=out_offset+i*2; | |
| 184 | + for (int k=0; k<2; k++) { | |
| 185 | + out_buff[out_index+k]=(byte)(value16>>(8*(1-k))); | |
| 186 | + } | |
| 187 | + } | |
| 188 | + return len_div_16*2; | |
| 189 | + } | |
| 190 | + else return -1; | |
| 191 | + } | |
| 192 | + | |
| 193 | + | |
| 194 | + /** Decodes the input chunk in_buff of G726_16 encoded data and returns | |
| 195 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 196 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 197 | + * out_coding value. */ | |
| 198 | + public static int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset, G726State state) { | |
| 199 | + | |
| 200 | + if (out_coding==AUDIO_ENCODING_ALAW || out_coding==AUDIO_ENCODING_ULAW) { | |
| 201 | + | |
| 202 | + int len_div_2=in_len/2; | |
| 203 | + for (int i=0; i<len_div_2; i++) { | |
| 204 | + int value8=0; | |
| 205 | + int in_index=in_offset+i*2; | |
| 206 | + for (int j=0; j<2; j++) { | |
| 207 | + value8+=unsignedInt(in_buff[in_index+j])<<(8*(1-j)); | |
| 208 | + } | |
| 209 | + int out_index=out_offset+i*8; | |
| 210 | + for (int k=0; k<8; k++) { | |
| 211 | + int in_value=(value8>>(2*(7-k)))&0x3; | |
| 212 | + int out_value=decode(in_value,out_coding,state); | |
| 213 | + out_buff[out_index+k]=(byte)out_value; | |
| 214 | + } | |
| 215 | + } | |
| 216 | + return len_div_2*8; | |
| 217 | + } | |
| 218 | + else | |
| 219 | + if (out_coding==AUDIO_ENCODING_LINEAR) { | |
| 220 | + | |
| 221 | + int len_div_2=in_len/2; | |
| 222 | + for (int i=0; i<len_div_2; i++) { | |
| 223 | + int value16=0; | |
| 224 | + int in_index=in_offset+i*2; | |
| 225 | + for (int j=0; j<2; j++) { | |
| 226 | + value16+=unsignedInt(in_buff[in_index+j])<<(8*(1-j)); | |
| 227 | + } | |
| 228 | + int out_index=out_offset+i*16; | |
| 229 | + for (int k=0; k<8; k++) { | |
| 230 | + int k2=k*2; | |
| 231 | + int in_value=(value16>>(2*(7-k)))&0x3; | |
| 232 | + //int out_value=G711.ulaw2linear(decode(in_value,AUDIO_ENCODING_ULAW,state)); | |
| 233 | + int out_value=decode(in_value,out_coding,state); | |
| 234 | + out_buff[out_index+k2]=(byte)(out_value&0xFF); | |
| 235 | + out_buff[out_index+k2+1]=(byte)(out_value>>8); | |
| 236 | + } | |
| 237 | + } | |
| 238 | + return len_div_2*16; | |
| 239 | + } | |
| 240 | + else return -1; | |
| 241 | + } | |
| 242 | + | |
| 243 | + | |
| 244 | + // ************************* NON-STATIC ************************* | |
| 245 | + | |
| 246 | + /** Creates a new G726_16 processor, that can be used to encode from or decode do PCM audio data. */ | |
| 247 | + public G726_16() { | |
| 248 | + super(16000); | |
| 249 | + } | |
| 250 | + | |
| 251 | + | |
| 252 | + /** Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens | |
| 253 | + * the resulting 5-bit CCITT G.726 40kbps code. | |
| 254 | + * Returns -1 if the input coding value is invalid. */ | |
| 255 | + public int encode(int sl, int in_coding) { | |
| 256 | + return encode(sl,in_coding,state); | |
| 257 | + } | |
| 258 | + | |
| 259 | + | |
| 260 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 261 | + * the G726_16 encoded chuck into out_buff. <br> | |
| 262 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 263 | + * in_coding value. */ | |
| 264 | + public int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset) { | |
| 265 | + return encode(in_buff,in_offset,in_len,in_coding,out_buff,out_offset,state); | |
| 266 | + } | |
| 267 | + | |
| 268 | + | |
| 269 | + /** Decodes a 5-bit CCITT G.726 40kbps code and returns | |
| 270 | + * the resulting 16-bit linear PCM, A-law or u-law sample value. | |
| 271 | + * -1 is returned if the output coding is unknown. */ | |
| 272 | + public int decode(int i, int out_coding) { | |
| 273 | + return decode(i,out_coding,state); | |
| 274 | + } | |
| 275 | + | |
| 276 | + | |
| 277 | + /** Decodes the input chunk in_buff of G726_16 encoded data and returns | |
| 278 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 279 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 280 | + * out_coding value. */ | |
| 281 | + public int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset) { | |
| 282 | + return decode(in_buff,in_offset,in_len,out_coding,out_buff,out_offset,state); | |
| 283 | + } | |
| 284 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/g726/G726_24.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/g726/G726_24.java | |
| 1 | +package cn.org.hentai.jtt1078.codec.g726; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.G711Codec; | |
| 4 | +import cn.org.hentai.jtt1078.codec.G711UCodec; | |
| 5 | + | |
| 6 | +/** G726_24 encoder and decoder. | |
| 7 | + * <p> | |
| 8 | + * These routines comprise an implementation of the CCITT G.726 24kbps | |
| 9 | + * ADPCM coding algorithm. Essentially, this implementation is identical to | |
| 10 | + * the bit level description except for a few deviations which take advantage | |
| 11 | + * of workstation attributes, such as hardware 2's complement arithmetic. | |
| 12 | + * <p> | |
| 13 | + * This implementation is based on the ANSI-C language reference implementations | |
| 14 | + * of the CCITT (International Telegraph and Telephone Consultative Committee) | |
| 15 | + * G.711, G.721 and G.723 voice compressions, provided by Sun Microsystems, Inc. | |
| 16 | + * <p> | |
| 17 | + * Acknowledgement to Sun Microsystems, Inc. for having released the original | |
| 18 | + * ANSI-C source code to the public domain. | |
| 19 | + */ | |
| 20 | +public class G726_24 extends G726 { | |
| 21 | + | |
| 22 | + // ##### C-to-Java conversion: ##### | |
| 23 | + // short becomes int | |
| 24 | + // char becomes int | |
| 25 | + // unsigned char becomes int | |
| 26 | + | |
| 27 | + | |
| 28 | + // *************************** STATIC *************************** | |
| 29 | + | |
| 30 | + /* | |
| 31 | + * Maps G726_24 code word to reconstructed scale factor normalized log | |
| 32 | + * magnitude values. | |
| 33 | + */ | |
| 34 | + static /*short*/int[] _dqlntab={-2048, 135, 273, 373, 373, 273, 135, -2048}; | |
| 35 | + | |
| 36 | + /* Maps G726_24 code word to log of scale factor multiplier. */ | |
| 37 | + static /*short*/int[] _witab={-128, 960, 4384, 18624, 18624, 4384, 960, -128}; | |
| 38 | + | |
| 39 | + /* | |
| 40 | + * Maps G726_24 code words to a set of values whose long and short | |
| 41 | + * term averages are computed and then compared to give an indication | |
| 42 | + * how stationary (steady state) the signal is. | |
| 43 | + */ | |
| 44 | + static /*short*/int[] _fitab={0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0}; | |
| 45 | + | |
| 46 | + static /*short*/int[] qtab_723_24={8, 218, 331}; | |
| 47 | + | |
| 48 | + /** Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code. | |
| 49 | + * Returns -1 if invalid input coding value. */ | |
| 50 | + public static int encode(int sl, int in_coding, G726State state) { | |
| 51 | + | |
| 52 | + /*short*/int sei, sezi, se, sez; /* ACCUM */ | |
| 53 | + /*short*/int d; /* SUBTA */ | |
| 54 | + /*short*/int y; /* MIX */ | |
| 55 | + /*short*/int sr; /* ADDB */ | |
| 56 | + /*short*/int dqsez; /* ADDC */ | |
| 57 | + /*short*/int dq, i; | |
| 58 | + | |
| 59 | + switch (in_coding) { | |
| 60 | + /* linearize input sample to 14-bit PCM */ | |
| 61 | + case AUDIO_ENCODING_ALAW: | |
| 62 | + sl= G711Codec.alaw2linear((byte)sl) >> 2; | |
| 63 | + break; | |
| 64 | + case AUDIO_ENCODING_ULAW: | |
| 65 | + sl= G711UCodec.ulaw2linear((byte)sl) >> 2; | |
| 66 | + break; | |
| 67 | + case AUDIO_ENCODING_LINEAR: | |
| 68 | + sl >>= 2; /* sl of 14-bit dynamic range */ | |
| 69 | + break; | |
| 70 | + default: | |
| 71 | + return (-1); | |
| 72 | + } | |
| 73 | + | |
| 74 | + sezi=state.predictor_zero(); | |
| 75 | + sez=sezi >> 1; | |
| 76 | + sei=sezi+state.predictor_pole(); | |
| 77 | + se=sei >> 1; /* se=estimated signal */ | |
| 78 | + | |
| 79 | + d=sl-se; /* d=estimation diff. */ | |
| 80 | + | |
| 81 | + /* quantize prediction difference d */ | |
| 82 | + y=state.step_size(); /* quantizer step size */ | |
| 83 | + i=quantize(d, y, qtab_723_24, 3); /* i=ADPCM code */ | |
| 84 | + dq=reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */ | |
| 85 | + | |
| 86 | + sr=(dq<0)? se-(dq & 0x3FFF) : se+dq; /* reconstructed signal */ | |
| 87 | + | |
| 88 | + dqsez=sr+sez-se; /* pole prediction diff. */ | |
| 89 | + | |
| 90 | + update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state); | |
| 91 | + | |
| 92 | + return (i); | |
| 93 | + } | |
| 94 | + | |
| 95 | + | |
| 96 | + /** Decodes a 3-bit CCITT G.726 24kbps ADPCM code and returns | |
| 97 | + * the resulting 16-bit linear PCM, A-law or u-law sample value. | |
| 98 | + * -1 is returned if the output coding is unknown. */ | |
| 99 | + public static int decode(int i, int out_coding, G726State state) { | |
| 100 | + | |
| 101 | + /*short*/int sezi, sei, sez, se; /* ACCUM */ | |
| 102 | + /*short*/int y; /* MIX */ | |
| 103 | + /*short*/int sr; /* ADDB */ | |
| 104 | + /*short*/int dq; | |
| 105 | + /*short*/int dqsez; | |
| 106 | + | |
| 107 | + i &= 0x07; /* mask to get proper bits */ | |
| 108 | + sezi=state.predictor_zero(); | |
| 109 | + sez=sezi >> 1; | |
| 110 | + sei=sezi+state.predictor_pole(); | |
| 111 | + se=sei >> 1; /* se=estimated signal */ | |
| 112 | + | |
| 113 | + y=state.step_size(); /* adaptive quantizer step size */ | |
| 114 | + dq=reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */ | |
| 115 | + | |
| 116 | + sr=(dq<0)? (se-(dq & 0x3FFF)) : (se+dq); /* reconst. signal */ | |
| 117 | + | |
| 118 | + dqsez=sr-se+sez; /* pole prediction diff. */ | |
| 119 | + | |
| 120 | + update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state); | |
| 121 | + | |
| 122 | + switch (out_coding) { | |
| 123 | + | |
| 124 | + case AUDIO_ENCODING_ALAW: | |
| 125 | + return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24)); | |
| 126 | + case AUDIO_ENCODING_ULAW: | |
| 127 | + return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24)); | |
| 128 | + case AUDIO_ENCODING_LINEAR: | |
| 129 | + return (sr << 2); /* sr was of 14-bit dynamic range */ | |
| 130 | + default: | |
| 131 | + return (-1); | |
| 132 | + } | |
| 133 | + } | |
| 134 | + | |
| 135 | + | |
| 136 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 137 | + * the G726_24 encoded chuck into out_buff. <br> | |
| 138 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 139 | + * in_coding value. */ | |
| 140 | + public static int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset, G726State state) { | |
| 141 | + | |
| 142 | + if (in_coding==AUDIO_ENCODING_ALAW || in_coding==AUDIO_ENCODING_ULAW) { | |
| 143 | + | |
| 144 | + int len_div_8=in_len/8; | |
| 145 | + for (int i=0; i<len_div_8; i++) { | |
| 146 | + int value8=0; | |
| 147 | + int i8=i*8; | |
| 148 | + for (int j=0; j<8; j++) { | |
| 149 | + int in_value=unsignedInt(in_buff[in_offset+i8+j]); | |
| 150 | + int out_value=encode(in_value,in_coding,state); | |
| 151 | + value8+=out_value<<(3*(7-j)); | |
| 152 | + } | |
| 153 | + int index=out_offset+i*3; | |
| 154 | + for (int k=0; k<3; k++) { | |
| 155 | + out_buff[index+k]=(byte)(value8>>(8*(2-k))); | |
| 156 | + } | |
| 157 | + } | |
| 158 | + return len_div_8*3; | |
| 159 | + } | |
| 160 | + else | |
| 161 | + if (in_coding==AUDIO_ENCODING_LINEAR) { | |
| 162 | + | |
| 163 | + int len_div_16=in_len/16; | |
| 164 | + for (int i=0; i<len_div_16; i++) { | |
| 165 | + int value16=0; | |
| 166 | + int in_index=in_offset+i*16; | |
| 167 | + for (int j=0; j<8; j++) { | |
| 168 | + int j2=j*2; | |
| 169 | + int in_value=signedIntLittleEndian(in_buff[in_index+j2+1],in_buff[in_index+j2]); | |
| 170 | + //int out_value=encode(G711.linear2ulaw(in_value),AUDIO_ENCODING_ULAW,state); | |
| 171 | + int out_value=encode(in_value,in_coding,state); | |
| 172 | + value16+=out_value<<(3*(7-j)); | |
| 173 | + } | |
| 174 | + int out_index=out_offset+i*3; | |
| 175 | + for (int k=0; k<3; k++) { | |
| 176 | + out_buff[out_index+k]=(byte)(value16>>(8*(2-k))); | |
| 177 | + } | |
| 178 | + } | |
| 179 | + return len_div_16*3; | |
| 180 | + } | |
| 181 | + else return -1; | |
| 182 | + } | |
| 183 | + | |
| 184 | + | |
| 185 | + /** Decodes the input chunk in_buff of G726_24 encoded data and returns | |
| 186 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 187 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 188 | + * out_coding value. */ | |
| 189 | + public static int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset, G726State state) { | |
| 190 | + | |
| 191 | + if (out_coding==AUDIO_ENCODING_ALAW || out_coding==AUDIO_ENCODING_ULAW) { | |
| 192 | + | |
| 193 | + int len_div_3=in_len/3; | |
| 194 | + for (int i=0; i<len_div_3; i++) { | |
| 195 | + int value8=0; | |
| 196 | + int in_index=in_offset+i*3; | |
| 197 | + for (int j=0; j<3; j++) { | |
| 198 | + value8+=unsignedInt(in_buff[in_index+j])<<(8*(2-j)); | |
| 199 | + } | |
| 200 | + int out_index=out_offset+i*8; | |
| 201 | + for (int k=0; k<8; k++) { | |
| 202 | + int in_value=(value8>>(3*(7-k)))&0x7; | |
| 203 | + int out_value=decode(in_value,out_coding,state); | |
| 204 | + out_buff[out_index+k]=(byte)out_value; | |
| 205 | + } | |
| 206 | + } | |
| 207 | + return len_div_3*8; | |
| 208 | + } | |
| 209 | + else | |
| 210 | + if (out_coding==AUDIO_ENCODING_LINEAR) { | |
| 211 | + | |
| 212 | + int len_div_3=in_len/3; | |
| 213 | + for (int i=0; i<len_div_3; i++) { | |
| 214 | + int value16=0; | |
| 215 | + int in_index=in_offset+i*3; | |
| 216 | + for (int j=0; j<3; j++) { | |
| 217 | + value16+=unsignedInt(in_buff[in_index+j])<<(8*(2-j)); | |
| 218 | + } | |
| 219 | + int out_index=out_offset+i*16; | |
| 220 | + for (int k=0; k<8; k++) { | |
| 221 | + int k2=k*2; | |
| 222 | + int in_value=(value16>>(3*(7-k)))&0x7; | |
| 223 | + //int out_value=G711.ulaw2linear(decode(in_value,AUDIO_ENCODING_ULAW,state)); | |
| 224 | + int out_value=decode(in_value,out_coding,state); | |
| 225 | + out_buff[out_index+k2]=(byte)(out_value&0xFF); | |
| 226 | + out_buff[out_index+k2+1]=(byte)(out_value>>8); | |
| 227 | + } | |
| 228 | + } | |
| 229 | + return len_div_3*16; | |
| 230 | + } | |
| 231 | + else return -1; | |
| 232 | + } | |
| 233 | + | |
| 234 | + | |
| 235 | + // ************************* NON-STATIC ************************* | |
| 236 | + | |
| 237 | + /** Creates a new G726_24 processor, that can be used to encode from or decode do PCM audio data. */ | |
| 238 | + public G726_24() { | |
| 239 | + super(24000); | |
| 240 | + } | |
| 241 | + | |
| 242 | + | |
| 243 | + /** Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code. | |
| 244 | + * Returns -1 if invalid input coding value. */ | |
| 245 | + public int encode(int sl, int in_coding) { | |
| 246 | + return encode(sl,in_coding,state); | |
| 247 | + } | |
| 248 | + | |
| 249 | + | |
| 250 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 251 | + * the G726_24 encoded chuck into out_buff. <br> | |
| 252 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 253 | + * in_coding value. */ | |
| 254 | + public int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset) { | |
| 255 | + return encode(in_buff,in_offset,in_len,in_coding,out_buff,out_offset,state); | |
| 256 | + } | |
| 257 | + | |
| 258 | + | |
| 259 | + /** Decodes a 3-bit CCITT G.726 24kbps ADPCM code and returns | |
| 260 | + * the resulting 16-bit linear PCM, A-law or u-law sample value. | |
| 261 | + * -1 is returned if the output coding is unknown. */ | |
| 262 | + public int decode(int i, int out_coding) { | |
| 263 | + return decode(i,out_coding,state); | |
| 264 | + } | |
| 265 | + | |
| 266 | + | |
| 267 | + /** Decodes the input chunk in_buff of G726_24 encoded data and returns | |
| 268 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 269 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 270 | + * out_coding value. */ | |
| 271 | + public int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset) { | |
| 272 | + return decode(in_buff,in_offset,in_len,out_coding,out_buff,out_offset,state); | |
| 273 | + } | |
| 274 | + | |
| 275 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/g726/G726_32.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/g726/G726_32.java | |
| 1 | + | |
| 2 | +package cn.org.hentai.jtt1078.codec.g726; | |
| 3 | + | |
| 4 | +import cn.org.hentai.jtt1078.codec.G711Codec; | |
| 5 | +import cn.org.hentai.jtt1078.codec.G711UCodec; | |
| 6 | + | |
| 7 | +/** G726_32 encoder and decoder. | |
| 8 | + * <p> | |
| 9 | + * These routines comprise an implementation of the CCITT G.726 32kbps ADPCM | |
| 10 | + * coding algorithm. Essentially, this implementation is identical to | |
| 11 | + * the bit level description except for a few deviations which | |
| 12 | + * take advantage of work station attributes, such as hardware 2's | |
| 13 | + * complement arithmetic and large memory. Specifically, certain time | |
| 14 | + * consuming operations such as multiplications are replaced | |
| 15 | + * with lookup tables and software 2's complement operations are | |
| 16 | + * replaced with hardware 2's complement. | |
| 17 | + * <p> | |
| 18 | + * The deviation from the bit level specification (lookup tables) | |
| 19 | + * preserves the bit level performance specifications. | |
| 20 | + * <p> | |
| 21 | + * As outlined in the G.726 Recommendation, the algorithm is broken | |
| 22 | + * down into modules. Each section of code below is preceded by | |
| 23 | + * the name of the module which it is implementing. | |
| 24 | + * <p> | |
| 25 | + * This implementation is based on the ANSI-C language reference implementations | |
| 26 | + * of the CCITT (International Telegraph and Telephone Consultative Committee) | |
| 27 | + * G.711, G.721 and G.723 voice compressions, provided by Sun Microsystems, Inc. | |
| 28 | + * <p> | |
| 29 | + * Acknowledgement to Sun Microsystems, Inc. for having released the original | |
| 30 | + * ANSI-C source code to the public domain. | |
| 31 | + */ | |
| 32 | +public class G726_32 extends G726 { | |
| 33 | + | |
| 34 | + // ##### C-to-Java conversion: ##### | |
| 35 | + // short becomes int | |
| 36 | + // char becomes int | |
| 37 | + // unsigned char becomes int | |
| 38 | + | |
| 39 | + | |
| 40 | + // *************************** STATIC *************************** | |
| 41 | + | |
| 42 | + static /*short*/int[] qtab_721={-124, 80, 178, 246, 300, 349, 400}; | |
| 43 | + /* | |
| 44 | + * Maps G726_32 code word to reconstructed scale factor normalized log | |
| 45 | + * magnitude values. | |
| 46 | + */ | |
| 47 | + static /*short*/int[] _dqlntab={-2048, 4, 135, 213, 273, 323, 373, 425, 425, 373, 323, 273, 213, 135, 4, -2048}; | |
| 48 | + | |
| 49 | + /* Maps G726_32 code word to log of scale factor multiplier. */ | |
| 50 | + static /*short*/int[] _witab={-12, 18, 41, 64, 112, 198, 355, 1122, 1122, 355, 198, 112, 64, 41, 18, -12}; | |
| 51 | + | |
| 52 | + /* | |
| 53 | + * Maps G726_32 code words to a set of values whose long and short | |
| 54 | + * term averages are computed and then compared to give an indication | |
| 55 | + * how stationary (steady state) the signal is. | |
| 56 | + */ | |
| 57 | + static /*short*/int[] _fitab={0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; | |
| 58 | + | |
| 59 | + /** Encodes the input vale of linear PCM, A-law or u-law data sl and returns | |
| 60 | + * the resulting code. -1 is returned for unknown input coding value. */ | |
| 61 | + public static int encode(int sl, int in_coding, G726State state) { | |
| 62 | + | |
| 63 | + /*short*/int sezi, se, sez; /* ACCUM */ | |
| 64 | + /*short*/int d; /* SUBTA */ | |
| 65 | + /*short*/int sr; /* ADDB */ | |
| 66 | + /*short*/int y; /* MIX */ | |
| 67 | + /*short*/int dqsez; /* ADDC */ | |
| 68 | + /*short*/int dq, i; | |
| 69 | + | |
| 70 | + switch (in_coding) { | |
| 71 | + /* linearize input sample to 14-bit PCM */ | |
| 72 | + case AUDIO_ENCODING_ALAW: | |
| 73 | + sl= G711Codec.alaw2linear((byte)sl) >> 2; | |
| 74 | + break; | |
| 75 | + case AUDIO_ENCODING_ULAW: | |
| 76 | + sl= G711UCodec.ulaw2linear((byte)sl) >> 2; | |
| 77 | + break; | |
| 78 | + case AUDIO_ENCODING_LINEAR: | |
| 79 | + sl >>= 2; /* 14-bit dynamic range */ | |
| 80 | + break; | |
| 81 | + default: | |
| 82 | + return -1; | |
| 83 | + } | |
| 84 | + | |
| 85 | + sezi=state.predictor_zero(); | |
| 86 | + sez=sezi >> 1; | |
| 87 | + se=(sezi+state.predictor_pole()) >> 1; /* estimated signal */ | |
| 88 | + | |
| 89 | + d=sl-se; /* estimation difference */ | |
| 90 | + | |
| 91 | + /* quantize the prediction difference */ | |
| 92 | + y=state.step_size(); /* quantizer step size */ | |
| 93 | + i=quantize(d, y, qtab_721, 7); /* i=ADPCM code */ | |
| 94 | + | |
| 95 | + dq=reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */ | |
| 96 | + | |
| 97 | + sr=(dq<0)? se-(dq & 0x3FFF) : se+dq; /* reconst. signal */ | |
| 98 | + | |
| 99 | + dqsez=sr+sez-se; /* pole prediction diff. */ | |
| 100 | + | |
| 101 | + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state); | |
| 102 | + | |
| 103 | + return i; | |
| 104 | + } | |
| 105 | + | |
| 106 | + /** Decodes a 4-bit code of G726_32 encoded data of i and | |
| 107 | + * returns the resulting linear PCM, A-law or u-law value. | |
| 108 | + * return -1 for unknown out_coding value. */ | |
| 109 | + public static int decode(int i, int out_coding, G726State state) { | |
| 110 | + | |
| 111 | + /*short*/int sezi, sei, sez, se; /* ACCUM */ | |
| 112 | + /*short*/int y; /* MIX */ | |
| 113 | + /*short*/int sr; /* ADDB */ | |
| 114 | + /*short*/int dq; | |
| 115 | + /*short*/int dqsez; | |
| 116 | + | |
| 117 | + i &= 0x0f; /* mask to get proper bits */ | |
| 118 | + sezi=state.predictor_zero(); | |
| 119 | + sez=sezi >> 1; | |
| 120 | + sei=sezi+state.predictor_pole(); | |
| 121 | + se=sei >> 1; /* se=estimated signal */ | |
| 122 | + | |
| 123 | + y=state.step_size(); /* dynamic quantizer step size */ | |
| 124 | + | |
| 125 | + dq=reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */ | |
| 126 | + | |
| 127 | + sr=(dq<0)? (se-(dq & 0x3FFF)) : se+dq; /* reconst. signal */ | |
| 128 | + | |
| 129 | + dqsez=sr-se+sez; /* pole prediction diff. */ | |
| 130 | + | |
| 131 | + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state); | |
| 132 | + | |
| 133 | + switch (out_coding) { | |
| 134 | + | |
| 135 | + case AUDIO_ENCODING_ALAW: | |
| 136 | + return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721)); | |
| 137 | + case AUDIO_ENCODING_ULAW: | |
| 138 | + return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721)); | |
| 139 | + case AUDIO_ENCODING_LINEAR: | |
| 140 | + return (sr << 2); /* sr was 14-bit dynamic range */ | |
| 141 | + default: | |
| 142 | + return -1; | |
| 143 | + } | |
| 144 | + } | |
| 145 | + | |
| 146 | + | |
| 147 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 148 | + * the G726_32 encoded chuck into out_buff. <br> | |
| 149 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 150 | + * in_coding value. */ | |
| 151 | + public static int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset, G726State state) { | |
| 152 | + | |
| 153 | + if (in_coding==AUDIO_ENCODING_ALAW || in_coding==AUDIO_ENCODING_ULAW) { | |
| 154 | + | |
| 155 | + /* | |
| 156 | + for (int i=0; i<in_len; i++) { | |
| 157 | + int in_value=in_buff[in_offset+i]; | |
| 158 | + int out_value=encode(in_value,in_coding,state); | |
| 159 | + int i_div_2=i/2; | |
| 160 | + if (i_div_2*2==i) | |
| 161 | + out_buff[out_offset+i_div_2]=(byte)(out_value<<4); | |
| 162 | + else | |
| 163 | + out_buff[out_offset+i_div_2]=(byte)(out_value+unsignedInt(out_buff[out_offset+i_div_2])); | |
| 164 | + } | |
| 165 | + return in_len/2; | |
| 166 | + */ | |
| 167 | + int len_div_2=in_len/2; | |
| 168 | + for (int i=0; i<len_div_2; i++) { | |
| 169 | + int in_index=in_offset+i*2; | |
| 170 | + int in_value1=in_buff[in_index]; | |
| 171 | + int in_value2=in_buff[in_index+1]; | |
| 172 | + int out_value1=encode(in_value1,in_coding,state); | |
| 173 | + int out_value2=encode(in_value2,in_coding,state); | |
| 174 | + out_buff[out_offset+i]=(byte)((out_value1<<4) + out_value2); | |
| 175 | + } | |
| 176 | + return len_div_2; | |
| 177 | + } | |
| 178 | + else | |
| 179 | + if (in_coding==AUDIO_ENCODING_LINEAR) { | |
| 180 | + | |
| 181 | + int len_div_4=in_len/4; | |
| 182 | + for (int i=0; i<len_div_4; i++) { | |
| 183 | + int in_index=in_offset+i*4; | |
| 184 | + int in_value1=signedIntLittleEndian(in_buff[in_index+1],in_buff[in_index+0]); | |
| 185 | + int in_value2=signedIntLittleEndian(in_buff[in_index+3],in_buff[in_index+2]); | |
| 186 | + | |
| 187 | + //int out_value1=encode(G711.linear2ulaw(in_value1),AUDIO_ENCODING_ULAW,state); | |
| 188 | + //int out_value2=encode(G711.linear2ulaw(in_value2),AUDIO_ENCODING_ULAW,state); | |
| 189 | + int out_value1=encode(in_value1,in_coding,state); | |
| 190 | + int out_value2=encode(in_value2,in_coding,state); | |
| 191 | + out_buff[out_offset+i]=(byte)((out_value1<<4) + out_value2); | |
| 192 | + } | |
| 193 | + return len_div_4; | |
| 194 | + } | |
| 195 | + else return -1; | |
| 196 | + } | |
| 197 | + | |
| 198 | + | |
| 199 | + /** Decodes the input chunk in_buff of G726_32 encoded data and returns | |
| 200 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 201 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 202 | + * out_coding value. */ | |
| 203 | + public static int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset, G726State state) { | |
| 204 | + | |
| 205 | + if (out_coding==AUDIO_ENCODING_ALAW || out_coding==AUDIO_ENCODING_ULAW) { | |
| 206 | + | |
| 207 | + /* | |
| 208 | + for (int i=0; i<in_len*2; i++) { | |
| 209 | + int in_value=unsignedInt(in_buff[in_offset+i/2]); | |
| 210 | + if ((i/2)*2==i) | |
| 211 | + in_value>>=4; | |
| 212 | + else | |
| 213 | + in_value%=0x10; | |
| 214 | + int out_value=decode(in_value,out_coding,state); | |
| 215 | + out_buff[out_offset+i]=(byte)out_value; | |
| 216 | + } | |
| 217 | + return in_len*2; | |
| 218 | + */ | |
| 219 | + for (int i=0; i<in_len; i++) { | |
| 220 | + int in_value=unsignedInt(in_buff[in_offset+i]); | |
| 221 | + int out_value1=decode(in_value>>4,out_coding,state); | |
| 222 | + int out_value2=decode(in_value&0xF,out_coding,state); | |
| 223 | + int out_index=out_offset+i*2; | |
| 224 | + out_buff[out_index]=(byte)out_value1; | |
| 225 | + out_buff[out_index+1]=(byte)out_value2; | |
| 226 | + } | |
| 227 | + return in_len*2; | |
| 228 | + } | |
| 229 | + else | |
| 230 | + if (out_coding==AUDIO_ENCODING_LINEAR) { | |
| 231 | + | |
| 232 | + for (int i=0; i<in_len; i++) { | |
| 233 | + int in_value=unsignedInt(in_buff[in_offset+i]); | |
| 234 | + //int out_value1=G711.ulaw2linear(decode(in_value>>4,AUDIO_ENCODING_ULAW,state)); | |
| 235 | + //int out_value2=G711.ulaw2linear(decode(in_value&0xF,AUDIO_ENCODING_ULAW,state)); | |
| 236 | + int out_value1=decode(in_value>>4,out_coding,state); | |
| 237 | + int out_value2=decode(in_value&0xF,out_coding,state); | |
| 238 | + int out_index=out_offset+i*4; | |
| 239 | + out_buff[out_index]=(byte)(out_value1&0xFF); | |
| 240 | + out_buff[out_index+1]=(byte)(out_value1>>8); | |
| 241 | + out_buff[out_index+2]=(byte)(out_value2&0xFF); | |
| 242 | + out_buff[out_index+3]=(byte)(out_value2>>8); | |
| 243 | + } | |
| 244 | + return in_len*4; | |
| 245 | + } | |
| 246 | + else return -1; | |
| 247 | + } | |
| 248 | + | |
| 249 | + | |
| 250 | + // ************************* NON-STATIC ************************* | |
| 251 | + | |
| 252 | + /** Creates a new G726_32 processor, that can be used to encode from or decode do PCM audio data. */ | |
| 253 | + public G726_32() { | |
| 254 | + super(32000); | |
| 255 | + } | |
| 256 | + | |
| 257 | + | |
| 258 | + /** Encodes the input vale of linear PCM, A-law or u-law data sl and returns | |
| 259 | + * the resulting code. -1 is returned for unknown input coding value. */ | |
| 260 | + public int encode(int sl, int in_coding) { | |
| 261 | + return encode(sl,in_coding,state); | |
| 262 | + } | |
| 263 | + | |
| 264 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 265 | + * the G726_32 encoded chuck into out_buff. <br> | |
| 266 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 267 | + * in_coding value. */ | |
| 268 | + public int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset) { | |
| 269 | + return encode(in_buff,in_offset,in_len,in_coding,out_buff,out_offset,state); | |
| 270 | + } | |
| 271 | + | |
| 272 | + | |
| 273 | + /** Decodes a 4-bit code of G726_32 encoded data of i and | |
| 274 | + * returns the resulting linear PCM, A-law or u-law value. | |
| 275 | + * return -1 for unknown out_coding value. */ | |
| 276 | + public int decode(int i, int out_coding) { | |
| 277 | + return decode(i,out_coding,state); | |
| 278 | + } | |
| 279 | + | |
| 280 | + | |
| 281 | + /** Decodes the input chunk in_buff of G726_32 encoded data and returns | |
| 282 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 283 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 284 | + * out_coding value. */ | |
| 285 | + public int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset) { | |
| 286 | + return decode(in_buff,in_offset,in_len,out_coding,out_buff,out_offset,state); | |
| 287 | + } | |
| 288 | + | |
| 289 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/codec/g726/G726_40.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/codec/g726/G726_40.java | |
| 1 | +package cn.org.hentai.jtt1078.codec.g726; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.G711Codec; | |
| 4 | +import cn.org.hentai.jtt1078.codec.G711UCodec; | |
| 5 | + | |
| 6 | +/** G726_40 encoder and decoder. | |
| 7 | + * <p> | |
| 8 | + * These routines comprise an implementation of the CCITT G.726 40kbps | |
| 9 | + * ADPCM coding algorithm. Essentially, this implementation is identical to | |
| 10 | + * the bit level description except for a few deviations which | |
| 11 | + * take advantage of workstation attributes, such as hardware 2's | |
| 12 | + * complement arithmetic. | |
| 13 | + * <p> | |
| 14 | + * The deviation from the bit level specification (lookup tables), | |
| 15 | + * preserves the bit level performance specifications. | |
| 16 | + * <p> | |
| 17 | + * As outlined in the G.723 Recommendation, the algorithm is broken | |
| 18 | + * down into modules. Each section of code below is preceded by | |
| 19 | + * the name of the module which it is implementing. | |
| 20 | + * <p> | |
| 21 | + * This implementation is based on the ANSI-C language reference implementations | |
| 22 | + * of the CCITT (International Telegraph and Telephone Consultative Committee) | |
| 23 | + * G.711, G.721 and G.723 voice compressions, provided by Sun Microsystems, Inc. | |
| 24 | + * <p> | |
| 25 | + * Acknowledgement to Sun Microsystems, Inc. for having released the original | |
| 26 | + * ANSI-C source code to the public domain. | |
| 27 | + */ | |
| 28 | +public class G726_40 extends G726 { | |
| 29 | + | |
| 30 | + // ##### C-to-Java conversion: ##### | |
| 31 | + // short becomes int | |
| 32 | + // char becomes int | |
| 33 | + // unsigned char becomes int | |
| 34 | + | |
| 35 | + | |
| 36 | + // *************************** STATIC *************************** | |
| 37 | + | |
| 38 | + /* | |
| 39 | + * Maps G723_40 code word to ructeconstructed scale factor normalized log | |
| 40 | + * magnitude values. | |
| 41 | + */ | |
| 42 | + static /*short*/int[] _dqlntab={-2048, -66, 28, 104, 169, 224, 274, 318, 358, 395, 429, 459, 488, 514, 539, 566, 566, 539, 514, 488, 459, 429, 395, 358, 318, 274, 224, 169, 104, 28, -66, -2048}; | |
| 43 | + | |
| 44 | + /* Maps G723_40 code word to log of scale factor multiplier. */ | |
| 45 | + static /*short*/int[] _witab={448, 448, 768, 1248, 1280, 1312, 1856, 3200, 4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272, 22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512, 3200, 1856, 1312, 1280, 1248, 768, 448, 448}; | |
| 46 | + | |
| 47 | + /* | |
| 48 | + * Maps G723_40 code words to a set of values whose long and short | |
| 49 | + * term averages are computed and then compared to give an indication | |
| 50 | + * how stationary (steady state) the signal is. | |
| 51 | + */ | |
| 52 | + static /*short*/int[] _fitab={0, 0, 0, 0, 0, 0x200, 0x200, 0x200, 0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00, 0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200, 0x200, 0x200, 0x200, 0, 0, 0, 0, 0}; | |
| 53 | + | |
| 54 | + static /*short*/int[] qtab_723_40={-122, -16, 68, 139, 198, 250, 298, 339, 378, 413, 445, 475, 502, 528, 553}; | |
| 55 | + | |
| 56 | + /** Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens | |
| 57 | + * the resulting 5-bit CCITT G726 40kbps code. | |
| 58 | + * Returns -1 if the input coding value is invalid. */ | |
| 59 | + public static int encode(int sl, int in_coding, G726State state) { | |
| 60 | + | |
| 61 | + /*short*/int sei, sezi, se, sez; /* ACCUM */ | |
| 62 | + /*short*/int d; /* SUBTA */ | |
| 63 | + /*short*/int y; /* MIX */ | |
| 64 | + /*short*/int sr; /* ADDB */ | |
| 65 | + /*short*/int dqsez; /* ADDC */ | |
| 66 | + /*short*/int dq, i; | |
| 67 | + | |
| 68 | + switch (in_coding) { | |
| 69 | + /* linearize input sample to 14-bit PCM */ | |
| 70 | + case AUDIO_ENCODING_ALAW: | |
| 71 | + sl= G711Codec.alaw2linear((byte) sl) >> 2; | |
| 72 | + break; | |
| 73 | + case AUDIO_ENCODING_ULAW: | |
| 74 | + sl= G711UCodec.ulaw2linear((byte)sl) >> 2; | |
| 75 | + break; | |
| 76 | + case AUDIO_ENCODING_LINEAR: | |
| 77 | + sl >>= 2; /* sl of 14-bit dynamic range */ | |
| 78 | + break; | |
| 79 | + default: | |
| 80 | + return (-1); | |
| 81 | + } | |
| 82 | + | |
| 83 | + sezi=state.predictor_zero(); | |
| 84 | + sez=sezi >> 1; | |
| 85 | + sei=sezi+state.predictor_pole(); | |
| 86 | + se=sei >> 1; /* se=estimated signal */ | |
| 87 | + | |
| 88 | + d=sl-se; /* d=estimation difference */ | |
| 89 | + | |
| 90 | + /* quantize prediction difference */ | |
| 91 | + y=state.step_size(); /* adaptive quantizer step size */ | |
| 92 | + i=quantize(d, y, qtab_723_40, 15); /* i=ADPCM code */ | |
| 93 | + | |
| 94 | + dq=reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */ | |
| 95 | + | |
| 96 | + sr=(dq<0)? se-(dq & 0x7FFF) : se+dq; /* reconstructed signal */ | |
| 97 | + | |
| 98 | + dqsez=sr+sez-se; /* dqsez=pole prediction diff. */ | |
| 99 | + | |
| 100 | + update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state); | |
| 101 | + | |
| 102 | + return (i); | |
| 103 | + } | |
| 104 | + | |
| 105 | + | |
| 106 | + /** Decodes a 5-bit CCITT G.726 40kbps code and returns | |
| 107 | + * the resulting 16-bit linear PCM, A-law or u-law sample value. | |
| 108 | + * -1 is returned if the output coding is unknown. */ | |
| 109 | + public static int decode(int i, int out_coding, G726State state) { | |
| 110 | + | |
| 111 | + /*short*/int sezi, sei, sez, se; /* ACCUM */ | |
| 112 | + /*short*/int y, dif; /* MIX */ | |
| 113 | + /*short*/int sr; /* ADDB */ | |
| 114 | + /*short*/int dq; | |
| 115 | + /*short*/int dqsez; | |
| 116 | + | |
| 117 | + i &= 0x1f; /* mask to get proper bits */ | |
| 118 | + sezi=state.predictor_zero(); | |
| 119 | + sez=sezi >> 1; | |
| 120 | + sei=sezi+state.predictor_pole(); | |
| 121 | + se=sei >> 1; /* se=estimated signal */ | |
| 122 | + | |
| 123 | + y=state.step_size(); /* adaptive quantizer step size */ | |
| 124 | + dq=reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */ | |
| 125 | + | |
| 126 | + sr=(dq<0)? (se-(dq & 0x7FFF)) : (se+dq); /* reconst. signal */ | |
| 127 | + | |
| 128 | + dqsez=sr-se+sez; /* pole prediction diff. */ | |
| 129 | + | |
| 130 | + update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state); | |
| 131 | + | |
| 132 | + switch (out_coding) { | |
| 133 | + | |
| 134 | + case AUDIO_ENCODING_ALAW: | |
| 135 | + return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40)); | |
| 136 | + case AUDIO_ENCODING_ULAW: | |
| 137 | + return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40)); | |
| 138 | + case AUDIO_ENCODING_LINEAR: | |
| 139 | + return (sr << 2); /* sr was of 14-bit dynamic range */ | |
| 140 | + default: | |
| 141 | + return (-1); | |
| 142 | + } | |
| 143 | + } | |
| 144 | + | |
| 145 | + | |
| 146 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 147 | + * the G726_40 encoded chuck into out_buff. <br> | |
| 148 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 149 | + * in_coding value. */ | |
| 150 | + public static int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset, G726State state) { | |
| 151 | + | |
| 152 | + if (in_coding==AUDIO_ENCODING_ALAW || in_coding==AUDIO_ENCODING_ULAW) { | |
| 153 | + | |
| 154 | + int len_div_8=in_len/8; | |
| 155 | + for (int i=0; i<len_div_8; i++) { | |
| 156 | + long value8=0; | |
| 157 | + int in_index=in_offset+i*8; | |
| 158 | + for (int j=0; j<8; j++) { | |
| 159 | + int in_value=unsignedInt(in_buff[in_index+j]); | |
| 160 | + int out_value=encode(in_value,in_coding,state); | |
| 161 | + value8+=((long)out_value)<<(5*(7-j)); | |
| 162 | + } | |
| 163 | + int out_index=out_offset+i*5; | |
| 164 | + for (int k=0; k<5; k++) { | |
| 165 | + out_buff[out_index+k]=(byte)(value8>>(8*(4-k))); | |
| 166 | + } | |
| 167 | + } | |
| 168 | + return len_div_8*5; | |
| 169 | + } | |
| 170 | + else | |
| 171 | + if (in_coding==AUDIO_ENCODING_LINEAR) { | |
| 172 | + | |
| 173 | + int len_div_16=in_len/16; | |
| 174 | + for (int i=0; i<len_div_16; i++) { | |
| 175 | + long value16=0; | |
| 176 | + int in_index=in_offset+i*16; | |
| 177 | + for (int j=0; j<8; j++) { | |
| 178 | + int j2=j*2; | |
| 179 | + int in_value=signedIntLittleEndian(in_buff[in_index+j2+1],in_buff[in_index+j2]); | |
| 180 | + int out_value=encode(in_value,in_coding,state); | |
| 181 | + value16+=((long)out_value)<<(5*(7-j)); | |
| 182 | + } | |
| 183 | + int out_index=out_offset+i*5; | |
| 184 | + for (int k=0; k<5; k++) { | |
| 185 | + out_buff[out_index+k]=(byte)(value16>>(8*(4-k))); | |
| 186 | + } | |
| 187 | + } | |
| 188 | + return len_div_16*5; | |
| 189 | + } | |
| 190 | + else return -1; | |
| 191 | + } | |
| 192 | + | |
| 193 | + | |
| 194 | + /** Decodes the input chunk in_buff of G726_40 encoded data and returns | |
| 195 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 196 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 197 | + * out_coding value. */ | |
| 198 | + public static int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset, G726State state) { | |
| 199 | + | |
| 200 | + if (out_coding==AUDIO_ENCODING_ALAW || out_coding==AUDIO_ENCODING_ULAW) { | |
| 201 | + | |
| 202 | + int len_div_5=in_len/5; | |
| 203 | + for (int i=0; i<len_div_5; i++) { | |
| 204 | + long value8=0; | |
| 205 | + int in_index=in_offset+i*5; | |
| 206 | + for (int j=0; j<5; j++) { | |
| 207 | + value8+=(long)unsignedInt(in_buff[in_index+j])<<(8*(4-j)); | |
| 208 | + } | |
| 209 | + int out_index=out_offset+i*8; | |
| 210 | + for (int k=0; k<8; k++) { | |
| 211 | + int in_value=(int)((value8>>(5*(7-k)))&0x1F); | |
| 212 | + int out_value=decode(in_value,out_coding,state); | |
| 213 | + out_buff[out_index+k]=(byte)out_value; | |
| 214 | + } | |
| 215 | + } | |
| 216 | + return len_div_5*8; | |
| 217 | + } | |
| 218 | + else | |
| 219 | + if (out_coding==AUDIO_ENCODING_LINEAR) { | |
| 220 | + | |
| 221 | + int len_div_5=in_len/5; | |
| 222 | + for (int i=0; i<len_div_5; i++) { | |
| 223 | + long value16=0; | |
| 224 | + int in_index=in_offset+i*5; | |
| 225 | + for (int j=0; j<5; j++) { | |
| 226 | + value16+=(long)unsignedInt(in_buff[in_index+j])<<(8*(4-j)); | |
| 227 | + } | |
| 228 | + int out_index=out_offset+i*16; | |
| 229 | + for (int k=0; k<8; k++) { | |
| 230 | + int k2=k*2; | |
| 231 | + int in_value=(int)((value16>>(5*(7-k)))&0x1F); | |
| 232 | + int out_value=decode(in_value,out_coding,state); | |
| 233 | + out_buff[out_index+k2]=(byte)(out_value&0xFF); | |
| 234 | + out_buff[out_index+k2+1]=(byte)(out_value>>8); | |
| 235 | + } | |
| 236 | + } | |
| 237 | + return len_div_5*16; | |
| 238 | + } | |
| 239 | + else return -1; | |
| 240 | + } | |
| 241 | + | |
| 242 | + | |
| 243 | + // ************************* NON-STATIC ************************* | |
| 244 | + | |
| 245 | + /** Creates a new G726_40 processor, that can be used to encode from or decode do PCM audio data. */ | |
| 246 | + public G726_40() { | |
| 247 | + super(40000); | |
| 248 | + } | |
| 249 | + | |
| 250 | + | |
| 251 | + /** Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens | |
| 252 | + * the resulting 5-bit CCITT G.726 40kbps code. | |
| 253 | + * Returns -1 if the input coding value is invalid. */ | |
| 254 | + public int encode(int sl, int in_coding) { | |
| 255 | + return encode(sl,in_coding,state); | |
| 256 | + } | |
| 257 | + | |
| 258 | + | |
| 259 | + /** Encodes the input chunk in_buff of linear PCM, A-law or u-law data and returns | |
| 260 | + * the G726_40 encoded chuck into out_buff. <br> | |
| 261 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 262 | + * in_coding value. */ | |
| 263 | + public int encode(byte[] in_buff, int in_offset, int in_len, int in_coding, byte[] out_buff, int out_offset) { | |
| 264 | + return encode(in_buff,in_offset,in_len,in_coding,out_buff,out_offset,state); | |
| 265 | + } | |
| 266 | + | |
| 267 | + | |
| 268 | + /** Decodes a 5-bit CCITT G.726 40kbps code and returns | |
| 269 | + * the resulting 16-bit linear PCM, A-law or u-law sample value. | |
| 270 | + * -1 is returned if the output coding is unknown. */ | |
| 271 | + public int decode(int i, int out_coding) { | |
| 272 | + return decode(i,out_coding,state); | |
| 273 | + } | |
| 274 | + | |
| 275 | + | |
| 276 | + /** Decodes the input chunk in_buff of G726_40 encoded data and returns | |
| 277 | + * the linear PCM, A-law or u-law chunk into out_buff. <br> | |
| 278 | + * It returns the actual size of the output data, or -1 in case of unknown | |
| 279 | + * out_coding value. */ | |
| 280 | + public int decode(byte[] in_buff, int in_offset, int in_len, int out_coding, byte[] out_buff, int out_offset) { | |
| 281 | + return decode(in_buff,in_offset,in_len,out_coding,out_buff,out_offset,state); | |
| 282 | + } | |
| 283 | + | |
| 284 | + | |
| 285 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/entity/Audio.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/entity/Audio.java | |
| 1 | +package cn.org.hentai.jtt1078.entity; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by houcheng on 2019-12-11. | |
| 5 | + */ | |
| 6 | +public class Audio extends Media | |
| 7 | +{ | |
| 8 | + public Audio(long sequence, MediaEncoding.Encoding encoding, byte[] data) | |
| 9 | + { | |
| 10 | + super(sequence, encoding, data); | |
| 11 | + } | |
| 12 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/entity/Media.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/entity/Media.java | |
| 1 | +package cn.org.hentai.jtt1078.entity; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by houcheng on 2019-12-11. | |
| 5 | + * 数据流,可能是视频或是音频,视频为FLV封装,音频为PCM编码的片断 | |
| 6 | + */ | |
| 7 | +public class Media | |
| 8 | +{ | |
| 9 | + public enum Type { Video, Audio }; | |
| 10 | + | |
| 11 | + public Type type; | |
| 12 | + public MediaEncoding.Encoding encoding; | |
| 13 | + public long sequence; | |
| 14 | + public byte[] data; | |
| 15 | + | |
| 16 | + public Media(long seq, MediaEncoding.Encoding encoding, byte[] data) | |
| 17 | + { | |
| 18 | + this.type = type; | |
| 19 | + this.data = data; | |
| 20 | + this.encoding = encoding; | |
| 21 | + this.sequence = seq; | |
| 22 | + } | |
| 23 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/entity/MediaEncoding.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/entity/MediaEncoding.java | |
| 1 | +package cn.org.hentai.jtt1078.entity; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by matrixy on 2019/12/20. | |
| 5 | + */ | |
| 6 | +public final class MediaEncoding | |
| 7 | +{ | |
| 8 | + public enum Encoding | |
| 9 | + { | |
| 10 | + RESERVED, | |
| 11 | + G721, | |
| 12 | + G722, | |
| 13 | + G723, | |
| 14 | + G728, | |
| 15 | + G729, | |
| 16 | + G711A, | |
| 17 | + G711U, | |
| 18 | + G726, | |
| 19 | + G729A, | |
| 20 | + DVI4_3, | |
| 21 | + DVI4_4, | |
| 22 | + DVI4_8K, | |
| 23 | + DVI4_16K, | |
| 24 | + LPC, | |
| 25 | + S16BE_STEREO, | |
| 26 | + S16BE_MONO, | |
| 27 | + MPEGAUDIO, | |
| 28 | + LPCM, | |
| 29 | + AAC, | |
| 30 | + WMA9STD, | |
| 31 | + HEAAC, | |
| 32 | + PCM_VOICE, | |
| 33 | + PCM_AUDIO, | |
| 34 | + AACLC, | |
| 35 | + MP3, | |
| 36 | + ADPCMA, | |
| 37 | + MP4AUDIO, | |
| 38 | + AMR, // 28 | |
| 39 | + | |
| 40 | + H264, // 98 | |
| 41 | + H265, | |
| 42 | + AVS, | |
| 43 | + SVAC, | |
| 44 | + UNKNOWN | |
| 45 | + } | |
| 46 | + | |
| 47 | + public static Encoding getEncoding(Media.Type type, int pt) | |
| 48 | + { | |
| 49 | + if (type.equals(Media.Type.Audio)) | |
| 50 | + { | |
| 51 | + if (pt >= 0 && pt <= 28) return Encoding.values()[pt]; | |
| 52 | + else return Encoding.UNKNOWN; | |
| 53 | + } | |
| 54 | + else | |
| 55 | + { | |
| 56 | + if (pt >= 98 && pt <= 101) return Encoding.values()[pt - 98 + 29]; | |
| 57 | + else return Encoding.UNKNOWN; | |
| 58 | + } | |
| 59 | + } | |
| 60 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/entity/Video.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/entity/Video.java | |
| 1 | +package cn.org.hentai.jtt1078.entity; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by houcheng on 2019-12-11. | |
| 5 | + */ | |
| 6 | +public class Video extends Media | |
| 7 | +{ | |
| 8 | + public Video(long sequence, MediaEncoding.Encoding encoding, byte[] data) | |
| 9 | + { | |
| 10 | + super(sequence, encoding, data); | |
| 11 | + } | |
| 12 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/flv/AudioTag.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/flv/AudioTag.java | |
| 1 | +package cn.org.hentai.jtt1078.flv; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * flv 音频封装 | |
| 5 | + * author:zhouyili (11861744@qq.com) | |
| 6 | + */ | |
| 7 | +public class AudioTag extends FlvTag{ | |
| 8 | + public static final byte MP3 = 2; | |
| 9 | + //UB[4] | |
| 10 | + //0 = Linear PCM, platform endian 根据编码的平台,一般用3而不用这个 | |
| 11 | + //1 = ADPCM | |
| 12 | + //2 = MP3 | |
| 13 | + //3 = Linear PCM, little endian | |
| 14 | + //4 = Nellymoser 16-kHz mono | |
| 15 | + //5 = Nellymoser 8-kHz mono | |
| 16 | + //6 = Nellymoser | |
| 17 | + //7 = G.711 A-law logarithmic PCM 8 = G.711 mu-law logarithmic PCM 9 = reserved | |
| 18 | + //10 = AAC | |
| 19 | + //11 = Speex | |
| 20 | + //14 = MP3 8-Khz | |
| 21 | + //15 = Device-specific sound | |
| 22 | + private byte format; | |
| 23 | + //0:5.5kHz,1:11kHz,2:22kHz,3:44kHz,format==10的话为3 | |
| 24 | + private byte rate; | |
| 25 | + //0:8bit,1:16bit | |
| 26 | + private byte size; | |
| 27 | + //0:mono,1:stereo,format==10的话为1 | |
| 28 | + private byte type; | |
| 29 | + //format==10是aac data,否则是对应编码后的数据 | |
| 30 | + private byte[] data; | |
| 31 | + | |
| 32 | + public AudioTag() { | |
| 33 | + } | |
| 34 | + | |
| 35 | + public AudioTag(int offSetTimestamp, int tagDataSize, byte format, byte rate, byte size, byte type, byte[] data) { | |
| 36 | + super(offSetTimestamp, tagDataSize); | |
| 37 | + this.format = format; | |
| 38 | + this.rate = rate; | |
| 39 | + this.size = size; | |
| 40 | + this.type = type; | |
| 41 | + this.data = data; | |
| 42 | + } | |
| 43 | + | |
| 44 | + public byte getFormat() { | |
| 45 | + return format; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public void setFormat(byte format) { | |
| 49 | + this.format = format; | |
| 50 | + } | |
| 51 | + | |
| 52 | + public byte getRate() { | |
| 53 | + return rate; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public void setRate(byte rate) { | |
| 57 | + this.rate = rate; | |
| 58 | + } | |
| 59 | + | |
| 60 | + public byte getSize() { | |
| 61 | + return size; | |
| 62 | + } | |
| 63 | + | |
| 64 | + public void setSize(byte size) { | |
| 65 | + this.size = size; | |
| 66 | + } | |
| 67 | + | |
| 68 | + public byte getType() { | |
| 69 | + return type; | |
| 70 | + } | |
| 71 | + | |
| 72 | + public void setType(byte type) { | |
| 73 | + this.type = type; | |
| 74 | + } | |
| 75 | + | |
| 76 | + public byte[] getData() { | |
| 77 | + return data; | |
| 78 | + } | |
| 79 | + | |
| 80 | + public void setData(byte[] data) { | |
| 81 | + this.data = data; | |
| 82 | + } | |
| 83 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/flv/FlvAudioTagEncoder.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/flv/FlvAudioTagEncoder.java | |
| 1 | +package cn.org.hentai.jtt1078.flv; | |
| 2 | + | |
| 3 | +import io.netty.buffer.ByteBuf; | |
| 4 | +import io.netty.buffer.Unpooled; | |
| 5 | +import org.slf4j.Logger; | |
| 6 | +import org.slf4j.LoggerFactory; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * Flv 音频封装编码 | |
| 10 | + * author:zhouyili (11861744@qq.com) | |
| 11 | + */ | |
| 12 | +public class FlvAudioTagEncoder { | |
| 13 | + public static final Logger log = LoggerFactory.getLogger(FlvAudioTagEncoder.class); | |
| 14 | + | |
| 15 | + public ByteBuf encode(AudioTag audioTag) throws Exception { | |
| 16 | + ByteBuf buffer = Unpooled.buffer(); | |
| 17 | + if (audioTag == null) return buffer; | |
| 18 | +// buffer.writeInt(audioTag.getPreTagSize()); | |
| 19 | + //----------------------tag header begin------- | |
| 20 | + buffer.writeByte(8); | |
| 21 | + buffer.writeMedium(audioTag.getTagDataSize()); | |
| 22 | + buffer.writeMedium(audioTag.getOffSetTimestamp() & 0xFFFFFF); | |
| 23 | + buffer.writeByte(audioTag.getOffSetTimestamp() >> 24); | |
| 24 | + buffer.writeMedium(audioTag.getStreamId()); | |
| 25 | + //---------------------tag header length 11--------- | |
| 26 | + //---------------------tag header end---------------- | |
| 27 | + byte formatAndRateAndSize = (byte) (audioTag.getFormat() << 4 | audioTag.getRate() << 2 | audioTag.getSize() << 1 | audioTag.getType()); | |
| 28 | + //-------------data begin------- | |
| 29 | + buffer.writeByte(formatAndRateAndSize); | |
| 30 | + buffer.writeBytes(audioTag.getData()); | |
| 31 | + //-------------data end ------- | |
| 32 | + buffer.writeInt(buffer.writerIndex());//应该等于11+tagDataSize | |
| 33 | + return buffer; | |
| 34 | + } | |
| 35 | + | |
| 36 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/flv/FlvEncoder.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/flv/FlvEncoder.java | |
| 1 | +package cn.org.hentai.jtt1078.flv; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 4 | + | |
| 5 | +import java.io.ByteArrayOutputStream; | |
| 6 | +import java.io.IOException; | |
| 7 | +import java.io.OutputStream; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by matrixy on 2020/1/3. | |
| 11 | + */ | |
| 12 | +public final class FlvEncoder | |
| 13 | +{ | |
| 14 | + Packet flvHeader; | |
| 15 | + Packet videoHeader; | |
| 16 | + Packet SPS, PPS; | |
| 17 | + int SPSSize, PPSSize; | |
| 18 | + boolean writeAVCSeqHeader; | |
| 19 | + int prevTagSize; | |
| 20 | + int streamID; | |
| 21 | + int videoTimeStamp; | |
| 22 | + byte[] lastIFrame; | |
| 23 | + | |
| 24 | + Packet _pAudioSpecificConfig; | |
| 25 | + int _nAudioConfigSize; | |
| 26 | + int _aacProfile; | |
| 27 | + int _sampleRateIndex; | |
| 28 | + int _channelConfig; | |
| 29 | + int _bWriteAACSeqHeader; | |
| 30 | + | |
| 31 | + boolean haveAudio, haveVideo; | |
| 32 | + | |
| 33 | + ByteArrayOutputStream videoFrame; | |
| 34 | + | |
| 35 | + public FlvEncoder(boolean haveVideo, boolean haveAudio) | |
| 36 | + { | |
| 37 | + this.haveVideo = haveVideo; | |
| 38 | + // this.haveAudio = haveAudio; | |
| 39 | + flvHeader = Packet.create(16); | |
| 40 | + videoFrame = new ByteArrayOutputStream(2048 * 100); | |
| 41 | + makeFlvHeader(); | |
| 42 | + } | |
| 43 | + | |
| 44 | + public Packet getHeader() | |
| 45 | + { | |
| 46 | + return flvHeader; | |
| 47 | + } | |
| 48 | + | |
| 49 | + public Packet getVideoHeader() | |
| 50 | + { | |
| 51 | + return videoHeader; | |
| 52 | + } | |
| 53 | + | |
| 54 | + public boolean videoReady() | |
| 55 | + { | |
| 56 | + return writeAVCSeqHeader; | |
| 57 | + } | |
| 58 | + | |
| 59 | + public byte[] getLastIFrame() | |
| 60 | + { | |
| 61 | + return this.lastIFrame; | |
| 62 | + } | |
| 63 | + | |
| 64 | + public byte[] write(byte[] nalu, int nTimeStamp) | |
| 65 | + { | |
| 66 | + this.videoTimeStamp = nTimeStamp; | |
| 67 | + | |
| 68 | + if (nalu == null || nalu.length <= 4) return null; | |
| 69 | + | |
| 70 | + int naluType = nalu[4] & 0x1f; | |
| 71 | + // skip SEI | |
| 72 | + if (naluType == 0x06) return null; | |
| 73 | + if (naluType == 0x01 | |
| 74 | + || naluType == 0x02 | |
| 75 | + || naluType == 0x03 | |
| 76 | + || naluType == 0x04 | |
| 77 | + || naluType == 0x05 | |
| 78 | + || naluType == 0x07 | |
| 79 | + || naluType == 0x08) ; else return null; | |
| 80 | + | |
| 81 | + if (SPS == null && naluType == 0x07) | |
| 82 | + { | |
| 83 | + SPS = Packet.create(nalu); | |
| 84 | + SPSSize = nalu.length; | |
| 85 | + } | |
| 86 | + if (PPS == null && naluType == 0x08) | |
| 87 | + { | |
| 88 | + PPS = Packet.create(nalu); | |
| 89 | + PPSSize = nalu.length; | |
| 90 | + } | |
| 91 | + if (SPS != null && PPS != null && writeAVCSeqHeader == false) | |
| 92 | + { | |
| 93 | + writeH264Header(nTimeStamp); | |
| 94 | + writeAVCSeqHeader = true; | |
| 95 | + } | |
| 96 | + if (writeAVCSeqHeader == false) return null; | |
| 97 | + | |
| 98 | + videoFrame.reset(); | |
| 99 | + writeH264Frame(nalu, nTimeStamp); | |
| 100 | + | |
| 101 | + if (videoFrame.size() == 0) return null; | |
| 102 | + | |
| 103 | + // 如果当前NAL单元为I祯,则缓存一个 | |
| 104 | + if (naluType == 0x05) | |
| 105 | + { | |
| 106 | + lastIFrame = videoFrame.toByteArray(); | |
| 107 | + } | |
| 108 | + | |
| 109 | + return videoFrame.toByteArray(); | |
| 110 | + } | |
| 111 | + | |
| 112 | + void makeFlvHeader() | |
| 113 | + { | |
| 114 | + flvHeader.addByte((byte)'F'); | |
| 115 | + flvHeader.addByte((byte)'L'); | |
| 116 | + flvHeader.addByte((byte)'V'); | |
| 117 | + flvHeader.addByte((byte)0x01); // version | |
| 118 | + flvHeader.addByte((byte)(0x00 | (haveVideo ? 0x01 : 0x00) | (haveAudio ? 0x04 : 0x00))); | |
| 119 | + flvHeader.addInt(0x09); | |
| 120 | + flvHeader.addInt(0x00); | |
| 121 | + } | |
| 122 | + | |
| 123 | + void writeH264Header(int nTimeStamp) | |
| 124 | + { | |
| 125 | + int nDataSize = 1 + 1 + 3 + 6 + 2 + (SPSSize - 4) + 1 + 2 + (PPSSize - 4); | |
| 126 | + videoHeader = Packet.create(nDataSize + 32); | |
| 127 | + | |
| 128 | + byte cTagType = 0x09; | |
| 129 | + videoHeader.addByte(cTagType); | |
| 130 | + | |
| 131 | + videoHeader.add3Bytes(nDataSize); | |
| 132 | + | |
| 133 | + videoHeader.add3Bytes(nTimeStamp); | |
| 134 | + videoHeader.addByte((byte)(nTimeStamp >> 24)); | |
| 135 | + | |
| 136 | + videoHeader.add3Bytes(streamID); | |
| 137 | + | |
| 138 | + byte cVideoParam = 0x17; | |
| 139 | + videoHeader.addByte(cVideoParam); | |
| 140 | + | |
| 141 | + byte cAVCPacketType = 0x00; | |
| 142 | + videoHeader.addByte(cAVCPacketType); | |
| 143 | + | |
| 144 | + videoHeader.add3Bytes(0x00); | |
| 145 | + | |
| 146 | + videoHeader.addByte((byte)0x01); | |
| 147 | + | |
| 148 | + videoHeader.addByte(SPS.seek(5).nextByte()); | |
| 149 | + videoHeader.addByte(SPS.seek(6).nextByte()); | |
| 150 | + videoHeader.addByte(SPS.seek(7).nextByte()); | |
| 151 | + videoHeader.addByte((byte)0xff); | |
| 152 | + videoHeader.addByte((byte)0xe1); | |
| 153 | + | |
| 154 | + videoHeader.addShort((short)(SPSSize - 4)); | |
| 155 | + videoHeader.addBytes(SPS.seek(4).nextBytes()); | |
| 156 | + videoHeader.addByte((byte)0x01); | |
| 157 | + | |
| 158 | + videoHeader.addShort((short)(PPSSize - 4)); | |
| 159 | + videoHeader.addBytes(PPS.seek(4).nextBytes()); | |
| 160 | + | |
| 161 | + prevTagSize = 11 + nDataSize; | |
| 162 | + videoHeader.addInt(prevTagSize); | |
| 163 | + } | |
| 164 | + | |
| 165 | + void writeH264Frame(byte[] nalu, int nTimeStamp) | |
| 166 | + { | |
| 167 | + int nNaluType = nalu[4] & 0x1f; | |
| 168 | + if (nNaluType == 7 || nNaluType == 8) return; | |
| 169 | + | |
| 170 | + writeByte(0x09); | |
| 171 | + | |
| 172 | + int nDataSize = 1 + 1 + 3 + 4 + (nalu.length - 4); | |
| 173 | + writeU3(nDataSize); | |
| 174 | + | |
| 175 | + writeU3(nTimeStamp); | |
| 176 | + writeByte(nTimeStamp >> 24); | |
| 177 | + | |
| 178 | + writeU3(streamID); | |
| 179 | + | |
| 180 | + if (nNaluType == 5) writeByte(0x17); | |
| 181 | + else writeByte(0x27); | |
| 182 | + | |
| 183 | + writeByte(0x01); | |
| 184 | + writeU3(0x00); | |
| 185 | + writeU4(nalu.length - 4); | |
| 186 | + writeBytes(nalu, 4, nalu.length - 4); | |
| 187 | + | |
| 188 | + prevTagSize = 11 + nDataSize; | |
| 189 | + | |
| 190 | + writeU4(prevTagSize); | |
| 191 | + } | |
| 192 | + | |
| 193 | + void write(byte u) | |
| 194 | + { | |
| 195 | + videoFrame.write(u); | |
| 196 | + } | |
| 197 | + | |
| 198 | + void writeBytes(byte[] data) | |
| 199 | + { | |
| 200 | + videoFrame.write(data, 0, data.length); | |
| 201 | + } | |
| 202 | + | |
| 203 | + void writeBytes(byte[] data, int offset, int len) | |
| 204 | + { | |
| 205 | + videoFrame.write(data, offset, len); | |
| 206 | + } | |
| 207 | + | |
| 208 | + void writeU4(int i) | |
| 209 | + { | |
| 210 | + write((byte)((i >> 24) & 0xff)); | |
| 211 | + write((byte)((i >> 16) & 0xff)); | |
| 212 | + write((byte)((i >> 8) & 0xff)); | |
| 213 | + write((byte)((i >> 0) & 0xff)); | |
| 214 | + } | |
| 215 | + | |
| 216 | + void writeU3(int i) | |
| 217 | + { | |
| 218 | + write((byte)((i >> 16) & 0xff)); | |
| 219 | + write((byte)((i >> 8) & 0xff)); | |
| 220 | + write((byte)((i >> 0) & 0xff)); | |
| 221 | + } | |
| 222 | + | |
| 223 | + void writeU2(int i) | |
| 224 | + { | |
| 225 | + write((byte)((i >> 8) & 0xff)); | |
| 226 | + write((byte)((i >> 0) & 0xff)); | |
| 227 | + } | |
| 228 | + | |
| 229 | + void writeByte(int i) | |
| 230 | + { | |
| 231 | + write((byte)(i & 0xff)); | |
| 232 | + } | |
| 233 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/flv/FlvTag.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/flv/FlvTag.java | |
| 1 | +package cn.org.hentai.jtt1078.flv; | |
| 2 | + | |
| 3 | +//由于flv格式是header+body,而body是preTagSize+currentTagData.......循环形式,并且第一个的preTagSize始终为0, | |
| 4 | +// 与其这样不如采用(header+preTag0Size)+(currentTagData+currentTagSize),这样就避免每次都要记录以下上一个tag的数据大小。 | |
| 5 | +/** | |
| 6 | + * author:zhouyili (11861744@qq.com) | |
| 7 | + */ | |
| 8 | +public class FlvTag { | |
| 9 | + public static final int AUDIO = 8; | |
| 10 | + public static final int VIDEO = 9; | |
| 11 | + public static final int SCRIPT = 18;//0x12 | |
| 12 | + private int preTagSize; | |
| 13 | + private byte tagType; | |
| 14 | + /**3个字节 streamId以后的数据长度*/ | |
| 15 | + private int tagDataSize; | |
| 16 | + //低3个字节写入后再写高位字节,相对于第一帧的时间偏移量,单位ms | |
| 17 | + private int offSetTimestamp; | |
| 18 | + //3个字节,一般总是0 | |
| 19 | + private int streamId; | |
| 20 | + | |
| 21 | + public FlvTag() { | |
| 22 | + } | |
| 23 | + | |
| 24 | + public FlvTag(int offSetTimestamp, int tagDataSize) { | |
| 25 | + this.tagDataSize = tagDataSize; | |
| 26 | + this.offSetTimestamp = offSetTimestamp; | |
| 27 | + } | |
| 28 | + | |
| 29 | + public int getPreTagSize() { | |
| 30 | + return preTagSize; | |
| 31 | + } | |
| 32 | + | |
| 33 | + public void setPreTagSize(int preTagSize) { | |
| 34 | + this.preTagSize = preTagSize; | |
| 35 | + } | |
| 36 | + | |
| 37 | + public byte getTagType() { | |
| 38 | + return tagType; | |
| 39 | + } | |
| 40 | + | |
| 41 | + public void setTagType(byte tagType) { | |
| 42 | + this.tagType = tagType; | |
| 43 | + } | |
| 44 | + | |
| 45 | + public int getTagDataSize() { | |
| 46 | + return tagDataSize; | |
| 47 | + } | |
| 48 | + | |
| 49 | + public void setTagDataSize(int tagDataSize) { | |
| 50 | + this.tagDataSize = tagDataSize; | |
| 51 | + } | |
| 52 | + | |
| 53 | + public int getOffSetTimestamp() { | |
| 54 | + return offSetTimestamp; | |
| 55 | + } | |
| 56 | + | |
| 57 | + public void setOffSetTimestamp(int offSetTimestamp) { | |
| 58 | + this.offSetTimestamp = offSetTimestamp; | |
| 59 | + } | |
| 60 | + | |
| 61 | + public int getStreamId() { | |
| 62 | + return streamId; | |
| 63 | + } | |
| 64 | + | |
| 65 | + public void setStreamId(int streamId) { | |
| 66 | + this.streamId = streamId; | |
| 67 | + } | |
| 68 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/http/GeneralResponseWriter.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/http/GeneralResponseWriter.java | |
| 1 | +package cn.org.hentai.jtt1078.http; | |
| 2 | + | |
| 3 | +import io.netty.buffer.ByteBuf; | |
| 4 | +import io.netty.channel.ChannelHandlerContext; | |
| 5 | +import io.netty.handler.codec.MessageToByteEncoder; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * Created by matrixy on 2019/11/25. | |
| 9 | + */ | |
| 10 | +public class GeneralResponseWriter extends MessageToByteEncoder<byte[]> | |
| 11 | +{ | |
| 12 | + @Override | |
| 13 | + protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) throws Exception | |
| 14 | + { | |
| 15 | + out.writeBytes(msg); | |
| 16 | + } | |
| 17 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/http/NettyHttpServerHandler.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/http/NettyHttpServerHandler.java | |
| 1 | +package cn.org.hentai.jtt1078.http; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.entity.Media; | |
| 4 | +import cn.org.hentai.jtt1078.publisher.PublishManager; | |
| 5 | +import cn.org.hentai.jtt1078.server.Session; | |
| 6 | +import cn.org.hentai.jtt1078.util.*; | |
| 7 | +import io.netty.buffer.ByteBuf; | |
| 8 | +import io.netty.buffer.Unpooled; | |
| 9 | +import io.netty.channel.ChannelHandlerContext; | |
| 10 | +import io.netty.channel.ChannelInboundHandlerAdapter; | |
| 11 | +import io.netty.handler.codec.http.*; | |
| 12 | +import io.netty.util.Attribute; | |
| 13 | +import io.netty.util.AttributeKey; | |
| 14 | +import org.slf4j.Logger; | |
| 15 | +import org.slf4j.LoggerFactory; | |
| 16 | + | |
| 17 | +import java.io.File; | |
| 18 | +import java.io.FileInputStream; | |
| 19 | +import java.net.InetSocketAddress; | |
| 20 | +import java.util.Base64; | |
| 21 | + | |
| 22 | +/** | |
| 23 | + * Created by matrixy on 2019/8/13. | |
| 24 | + */ | |
| 25 | +public class NettyHttpServerHandler extends ChannelInboundHandlerAdapter | |
| 26 | +{ | |
| 27 | + static Logger logger = LoggerFactory.getLogger(NettyHttpServerHandler.class); | |
| 28 | + static final byte[] HTTP_403_DATA = "<h1>403 Forbidden</h1><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding--><!--padding-->".getBytes(); | |
| 29 | + static final String HEADER_ENCODING = "ISO-8859-1"; | |
| 30 | + | |
| 31 | + private static final AttributeKey<Session> SESSION_KEY = AttributeKey.valueOf("session"); | |
| 32 | + | |
| 33 | + @Override | |
| 34 | + public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception | |
| 35 | + { | |
| 36 | + FullHttpRequest fhr = (FullHttpRequest) msg; | |
| 37 | + String uri = fhr.uri(); | |
| 38 | + Packet resp = Packet.create(1024); | |
| 39 | + // uri的第二段,就是通道标签 | |
| 40 | + if (uri.startsWith("/video/")) | |
| 41 | + { | |
| 42 | + String tag = uri.substring("/video/".length()); | |
| 43 | + | |
| 44 | + resp.addBytes("HTTP/1.1 200 OK\r\n".getBytes(HEADER_ENCODING)); | |
| 45 | + resp.addBytes("Connection: keep-alive\r\n".getBytes(HEADER_ENCODING)); | |
| 46 | + resp.addBytes("Content-Type: video/x-flv\r\n".getBytes(HEADER_ENCODING)); | |
| 47 | + resp.addBytes("Transfer-Encoding: chunked\r\n".getBytes(HEADER_ENCODING)); | |
| 48 | + resp.addBytes("Cache-Control: no-cache\r\n".getBytes(HEADER_ENCODING)); | |
| 49 | + resp.addBytes("Access-Control-Allow-Origin: *\r\n".getBytes(HEADER_ENCODING)); | |
| 50 | + resp.addBytes("Access-Control-Allow-Credentials: true\r\n".getBytes(HEADER_ENCODING)); | |
| 51 | + resp.addBytes("\r\n".getBytes(HEADER_ENCODING)); | |
| 52 | + | |
| 53 | + ctx.writeAndFlush(resp.getBytes()).await(); | |
| 54 | + | |
| 55 | + // 订阅视频数据 | |
| 56 | + long wid = PublishManager.getInstance().subscribe(tag, Media.Type.Video, ctx).getId(); | |
| 57 | + setSession(ctx, new Session().set("subscriber-id", wid).set("tag", tag)); | |
| 58 | + } | |
| 59 | + else if (uri.equals("/test/multimedia")) | |
| 60 | + { | |
| 61 | + responseHTMLFile("/multimedia.html", ctx); | |
| 62 | + } | |
| 63 | + else | |
| 64 | + { | |
| 65 | + | |
| 66 | + ByteBuf body = Unpooled.buffer(HTTP_403_DATA.length); | |
| 67 | + body.writeBytes(HTTP_403_DATA); | |
| 68 | + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(403), body); | |
| 69 | + response.headers().add("Content-Length", HTTP_403_DATA.length); | |
| 70 | + ctx.writeAndFlush(response).await(); | |
| 71 | + ctx.flush(); | |
| 72 | + } | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Override | |
| 76 | + public void channelInactive(ChannelHandlerContext ctx) throws Exception | |
| 77 | + { | |
| 78 | + super.channelInactive(ctx); | |
| 79 | + Session session = getSession(ctx); | |
| 80 | + if (session != null && session.has("subscriber-id") && session.has("tag")) | |
| 81 | + { | |
| 82 | + String tag = session.get("tag"); | |
| 83 | + Long wid = session.get("subscriber-id"); | |
| 84 | + PublishManager.getInstance().unsubscribe(tag, wid); | |
| 85 | + } | |
| 86 | + } | |
| 87 | + | |
| 88 | + // 响应静态文件内容 | |
| 89 | + private void responseHTMLFile(String htmlFilePath, ChannelHandlerContext ctx) | |
| 90 | + { | |
| 91 | + byte[] fileData = FileUtils.read(NettyHttpServerHandler.class.getResourceAsStream(htmlFilePath)); | |
| 92 | + ByteBuf body = Unpooled.buffer(fileData.length); | |
| 93 | + body.writeBytes(fileData); | |
| 94 | + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(200), body); | |
| 95 | + response.headers().add("Content-Length", fileData.length); | |
| 96 | + ctx.write(response); | |
| 97 | + ctx.flush(); | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception | |
| 102 | + { | |
| 103 | + ctx.flush(); | |
| 104 | + } | |
| 105 | + | |
| 106 | + @Override | |
| 107 | + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception | |
| 108 | + { | |
| 109 | + ctx.close(); | |
| 110 | + cause.printStackTrace(); | |
| 111 | + } | |
| 112 | + | |
| 113 | + public final void setSession(ChannelHandlerContext context, Session session) | |
| 114 | + { | |
| 115 | + context.channel().attr(SESSION_KEY).set(session); | |
| 116 | + } | |
| 117 | + | |
| 118 | + public final Session getSession(ChannelHandlerContext context) | |
| 119 | + { | |
| 120 | + Attribute<Session> attr = context.channel().attr(SESSION_KEY); | |
| 121 | + if (null == attr) return null; | |
| 122 | + else return attr.get(); | |
| 123 | + } | |
| 124 | +} | |
| 125 | + | ... | ... |
src/main/java/cn/org/hentai/jtt1078/publisher/Channel.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/publisher/Channel.java | |
| 1 | +package cn.org.hentai.jtt1078.publisher; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.AudioCodec; | |
| 4 | +import cn.org.hentai.jtt1078.entity.Media; | |
| 5 | +import cn.org.hentai.jtt1078.entity.MediaEncoding; | |
| 6 | +import cn.org.hentai.jtt1078.flv.FlvEncoder; | |
| 7 | +import cn.org.hentai.jtt1078.subscriber.RTMPPublisher; | |
| 8 | +import cn.org.hentai.jtt1078.subscriber.Subscriber; | |
| 9 | +import cn.org.hentai.jtt1078.subscriber.VideoSubscriber; | |
| 10 | +import cn.org.hentai.jtt1078.util.ByteHolder; | |
| 11 | +import cn.org.hentai.jtt1078.util.Configs; | |
| 12 | +import io.netty.channel.ChannelHandlerContext; | |
| 13 | +import org.apache.commons.lang.StringUtils; | |
| 14 | +import org.slf4j.Logger; | |
| 15 | +import org.slf4j.LoggerFactory; | |
| 16 | + | |
| 17 | +import java.util.Iterator; | |
| 18 | +import java.util.concurrent.ConcurrentLinkedQueue; | |
| 19 | + | |
| 20 | +/** | |
| 21 | + * Created by matrixy on 2020/1/11. | |
| 22 | + */ | |
| 23 | +public class Channel | |
| 24 | +{ | |
| 25 | + static Logger logger = LoggerFactory.getLogger(Channel.class); | |
| 26 | + | |
| 27 | + ConcurrentLinkedQueue<Subscriber> subscribers; | |
| 28 | + RTMPPublisher rtmpPublisher; | |
| 29 | + | |
| 30 | + String tag; | |
| 31 | + boolean publishing; | |
| 32 | + ByteHolder buffer; | |
| 33 | + AudioCodec audioCodec; | |
| 34 | + FlvEncoder flvEncoder; | |
| 35 | + private long firstTimestamp = -1; | |
| 36 | + | |
| 37 | + public Channel(String tag) | |
| 38 | + { | |
| 39 | + this.tag = tag; | |
| 40 | + this.subscribers = new ConcurrentLinkedQueue<Subscriber>(); | |
| 41 | + this.flvEncoder = new FlvEncoder(true, true); | |
| 42 | + this.buffer = new ByteHolder(2048 * 100); | |
| 43 | + | |
| 44 | + if (StringUtils.isEmpty(Configs.get("rtmp.url")) == false) | |
| 45 | + { | |
| 46 | + rtmpPublisher = new RTMPPublisher(tag); | |
| 47 | + rtmpPublisher.start(); | |
| 48 | + } | |
| 49 | + } | |
| 50 | + | |
| 51 | + public boolean isPublishing() | |
| 52 | + { | |
| 53 | + return publishing; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public Subscriber subscribe(ChannelHandlerContext ctx) | |
| 57 | + { | |
| 58 | + logger.info("channel: {} -> {}, subscriber: {}", Long.toHexString(hashCode() & 0xffffffffL), tag, ctx.channel().remoteAddress().toString()); | |
| 59 | + | |
| 60 | + Subscriber subscriber = new VideoSubscriber(this.tag, ctx); | |
| 61 | + this.subscribers.add(subscriber); | |
| 62 | + return subscriber; | |
| 63 | + } | |
| 64 | + | |
| 65 | + public void writeAudio(long timestamp, int pt, byte[] data) | |
| 66 | + { | |
| 67 | + if (audioCodec == null) | |
| 68 | + { | |
| 69 | + audioCodec = AudioCodec.getCodec(pt); | |
| 70 | + logger.info("audio codec: {}", MediaEncoding.getEncoding(Media.Type.Audio, pt)); | |
| 71 | + } | |
| 72 | + broadcastAudio(timestamp, audioCodec.toPCM(data)); | |
| 73 | + } | |
| 74 | + | |
| 75 | + public void writeVideo(long sequence, long timeoffset, int payloadType, byte[] h264) | |
| 76 | + { | |
| 77 | + if (firstTimestamp == -1) firstTimestamp = timeoffset; | |
| 78 | + this.publishing = true; | |
| 79 | + this.buffer.write(h264); | |
| 80 | + while (true) | |
| 81 | + { | |
| 82 | + byte[] nalu = readNalu(); | |
| 83 | + if (nalu == null) break; | |
| 84 | + if (nalu.length < 4) continue; | |
| 85 | + | |
| 86 | + byte[] flvTag = this.flvEncoder.write(nalu, (int) (timeoffset - firstTimestamp)); | |
| 87 | + | |
| 88 | + if (flvTag == null) continue; | |
| 89 | + | |
| 90 | + // 广播给所有的观众 | |
| 91 | + broadcastVideo(timeoffset, flvTag); | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + public void writeVideoRtp(byte[] h264) { | |
| 96 | + | |
| 97 | + } | |
| 98 | + | |
| 99 | + public void broadcastVideo(long timeoffset, byte[] flvTag) | |
| 100 | + { | |
| 101 | + for (Subscriber subscriber : subscribers) | |
| 102 | + { | |
| 103 | + subscriber.onVideoData(timeoffset, flvTag, flvEncoder); | |
| 104 | + } | |
| 105 | + } | |
| 106 | + | |
| 107 | + public void broadcastAudio(long timeoffset, byte[] flvTag) | |
| 108 | + { | |
| 109 | + for (Subscriber subscriber : subscribers) | |
| 110 | + { | |
| 111 | + subscriber.onAudioData(timeoffset, flvTag, flvEncoder); | |
| 112 | + } | |
| 113 | + } | |
| 114 | + | |
| 115 | + public void unsubscribe(long watcherId) | |
| 116 | + { | |
| 117 | + for (Iterator<Subscriber> itr = subscribers.iterator(); itr.hasNext(); ) | |
| 118 | + { | |
| 119 | + Subscriber subscriber = itr.next(); | |
| 120 | + if (subscriber.getId() == watcherId) | |
| 121 | + { | |
| 122 | + itr.remove(); | |
| 123 | + subscriber.close(); | |
| 124 | + return; | |
| 125 | + } | |
| 126 | + } | |
| 127 | + } | |
| 128 | + | |
| 129 | + public void close() | |
| 130 | + { | |
| 131 | + for (Iterator<Subscriber> itr = subscribers.iterator(); itr.hasNext(); ) | |
| 132 | + { | |
| 133 | + Subscriber subscriber = itr.next(); | |
| 134 | + subscriber.close(); | |
| 135 | + itr.remove(); | |
| 136 | + } | |
| 137 | + if (rtmpPublisher != null) rtmpPublisher.close(); | |
| 138 | + } | |
| 139 | + | |
| 140 | + private byte[] readNalu() | |
| 141 | + { | |
| 142 | + for (int i = 0; i < buffer.size() - 3; i++) | |
| 143 | + { | |
| 144 | + int a = buffer.get(i + 0) & 0xff; | |
| 145 | + int b = buffer.get(i + 1) & 0xff; | |
| 146 | + int c = buffer.get(i + 2) & 0xff; | |
| 147 | + int d = buffer.get(i + 3) & 0xff; | |
| 148 | + if (a == 0x00 && b == 0x00 && c == 0x00 && d == 0x01) | |
| 149 | + { | |
| 150 | + if (i == 0) continue; | |
| 151 | + byte[] nalu = new byte[i]; | |
| 152 | + buffer.sliceInto(nalu, i); | |
| 153 | + //System.out.println(nalu.length); | |
| 154 | + //System.out.println(toHex(nalu)); | |
| 155 | + return nalu; | |
| 156 | + } | |
| 157 | + } | |
| 158 | + return null; | |
| 159 | + } | |
| 160 | + | |
| 161 | + public String toHex(byte[] bytes) { | |
| 162 | + StringBuilder sb = new StringBuilder(); | |
| 163 | + for (byte b : bytes) { | |
| 164 | + sb.append(String.format("%02X ", b)); | |
| 165 | + } | |
| 166 | + | |
| 167 | + return sb.toString(); | |
| 168 | + } | |
| 169 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/publisher/PublishManager.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/publisher/PublishManager.java | |
| 1 | +package cn.org.hentai.jtt1078.publisher; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.entity.Media; | |
| 4 | +import cn.org.hentai.jtt1078.subscriber.Subscriber; | |
| 5 | +import io.netty.channel.ChannelHandlerContext; | |
| 6 | +import org.slf4j.Logger; | |
| 7 | +import org.slf4j.LoggerFactory; | |
| 8 | + | |
| 9 | +import java.util.concurrent.ConcurrentHashMap; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * Created by houcheng on 2019-12-11. | |
| 13 | + */ | |
| 14 | +public final class PublishManager | |
| 15 | +{ | |
| 16 | + static Logger logger = LoggerFactory.getLogger(PublishManager.class); | |
| 17 | + ConcurrentHashMap<String, Channel> channels; | |
| 18 | + | |
| 19 | + private PublishManager() | |
| 20 | + { | |
| 21 | + channels = new ConcurrentHashMap<String, Channel>(); | |
| 22 | + } | |
| 23 | + | |
| 24 | + public Subscriber subscribe(String tag, Media.Type type, ChannelHandlerContext ctx) | |
| 25 | + { | |
| 26 | + Channel chl = channels.get(tag); | |
| 27 | + if (chl == null) | |
| 28 | + { | |
| 29 | + chl = new Channel(tag); | |
| 30 | + channels.put(tag, chl); | |
| 31 | + } | |
| 32 | + Subscriber subscriber = null; | |
| 33 | + if (type.equals(Media.Type.Video)) subscriber = chl.subscribe(ctx); | |
| 34 | + else throw new RuntimeException("unknown media type: " + type); | |
| 35 | + | |
| 36 | + subscriber.setName("subscriber-" + tag + "-" + subscriber.getId()); | |
| 37 | + subscriber.start(); | |
| 38 | + | |
| 39 | + return subscriber; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public void publishAudio(String tag, int sequence, long timestamp, int payloadType, byte[] data) | |
| 43 | + { | |
| 44 | + Channel chl = channels.get(tag); | |
| 45 | + if (chl != null) chl.writeAudio(timestamp, payloadType, data); | |
| 46 | + } | |
| 47 | + | |
| 48 | + public void publishVideo(String tag, int sequence, long timestamp, int payloadType, byte[] data) | |
| 49 | + { | |
| 50 | + Channel chl = channels.get(tag); | |
| 51 | + if (chl != null) chl.writeVideo(sequence, timestamp, payloadType, data); | |
| 52 | + } | |
| 53 | + | |
| 54 | + public Channel open(String tag) | |
| 55 | + { | |
| 56 | + Channel chl = channels.get(tag); | |
| 57 | + if (chl == null) | |
| 58 | + { | |
| 59 | + chl = new Channel(tag); | |
| 60 | + channels.put(tag, chl); | |
| 61 | + } | |
| 62 | + if (chl.isPublishing()) throw new RuntimeException("channel already publishing"); | |
| 63 | + return chl; | |
| 64 | + } | |
| 65 | + | |
| 66 | + public void close(String tag) | |
| 67 | + { | |
| 68 | + Channel chl = channels.remove(tag); | |
| 69 | + if (chl != null) chl.close(); | |
| 70 | + } | |
| 71 | + | |
| 72 | + public void unsubscribe(String tag, long watcherId) | |
| 73 | + { | |
| 74 | + Channel chl = channels.get(tag); | |
| 75 | + if (chl != null) chl.unsubscribe(watcherId); | |
| 76 | + logger.info("unsubscribe: {} - {}", tag, watcherId); | |
| 77 | + } | |
| 78 | + static final PublishManager instance = new PublishManager(); | |
| 79 | + public static void init() { } | |
| 80 | + | |
| 81 | + public static PublishManager getInstance() | |
| 82 | + { | |
| 83 | + return instance; | |
| 84 | + } | |
| 85 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/rtp/H264Packeter.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/rtp/H264Packeter.java | |
| 1 | +package cn.org.hentai.jtt1078.rtp; | |
| 2 | + | |
| 3 | +import java.nio.ByteBuffer; | |
| 4 | +import java.util.ArrayList; | |
| 5 | +import java.util.Arrays; | |
| 6 | +import java.util.List; | |
| 7 | + | |
| 8 | +public class H264Packeter { | |
| 9 | + | |
| 10 | + private final int MAX_PACKAGE_SIZE = 1400; | |
| 11 | + | |
| 12 | + private byte[] buffer; | |
| 13 | + | |
| 14 | + private long firstTimestamp = 0; | |
| 15 | + | |
| 16 | + private int seq = 0; | |
| 17 | + | |
| 18 | + private int lastPosition = 0; | |
| 19 | + | |
| 20 | + public List<byte[]> packet(byte[] h264, long timestamp) { | |
| 21 | + List<byte[]> streams = new ArrayList<>(); | |
| 22 | + if (buffer == null) { | |
| 23 | + buffer = Arrays.copyOf(h264, h264.length); | |
| 24 | + } else { | |
| 25 | + byte[] nbuffer = new byte[buffer.length - lastPosition + h264.length]; | |
| 26 | + System.arraycopy(buffer, lastPosition, nbuffer, 0, buffer.length - lastPosition); | |
| 27 | + //System.out.println(toHex(nbuffer)); | |
| 28 | + System.arraycopy(h264, 0, nbuffer, buffer.length - lastPosition, h264.length); | |
| 29 | + //System.out.println(toHex(nbuffer)); | |
| 30 | + buffer = nbuffer; | |
| 31 | + } | |
| 32 | + lastPosition = 0; | |
| 33 | + //System.out.println(buffer.length); | |
| 34 | + if (firstTimestamp == 0) { | |
| 35 | + firstTimestamp = timestamp; | |
| 36 | + } | |
| 37 | + while (lastPosition < buffer.length - 4) { | |
| 38 | + byte[] nalu = readNalu(); | |
| 39 | + if (nalu == null) { | |
| 40 | + break; | |
| 41 | + } | |
| 42 | + ByteBuffer buffer = null; | |
| 43 | + byte[] header = new byte[14]; | |
| 44 | + header[0] = (byte) (header[0] | 0x80); | |
| 45 | + header[1] = (byte) (header[1] | 96); | |
| 46 | + header[11] = 15; | |
| 47 | + if (nalu.length <= MAX_PACKAGE_SIZE) { | |
| 48 | + buffer = ByteBuffer.allocate(16 + nalu.length); | |
| 49 | + header[1] = (byte) (header[1] | 0x80); | |
| 50 | + buffer.put((byte) 0x24); | |
| 51 | + buffer.put((byte) 0); | |
| 52 | + buffer.putShort((short) (12 + nalu.length)); | |
| 53 | + buffer.put(header, 0, 2); | |
| 54 | + buffer.putShort((short) ++seq); | |
| 55 | + buffer.putInt((int) (timestamp - firstTimestamp)); | |
| 56 | + buffer.put(header, 8, 4); | |
| 57 | + buffer.put(nalu); | |
| 58 | + //System.out.println("完整: " + toHex(buffer.array())); | |
| 59 | + streams.add(buffer.array()); | |
| 60 | + } else { | |
| 61 | + int tail = nalu.length % MAX_PACKAGE_SIZE, group = nalu.length / MAX_PACKAGE_SIZE + (tail > 0 ? 1 : 0); | |
| 62 | + for (int i = 0; i < group; i++) { | |
| 63 | + buffer = ByteBuffer.allocate(18 + MAX_PACKAGE_SIZE); | |
| 64 | + if (i == 0) { | |
| 65 | + buffer = ByteBuffer.allocate(17 + MAX_PACKAGE_SIZE); | |
| 66 | + header[1] = (byte) (header[1] & 0x7F); | |
| 67 | + header[12] = (byte) (header[12] | ((byte) (nalu[0] & 0x80)) << 7); | |
| 68 | + header[12] = (byte) (header[12] | ((byte) ((nalu[0] & 0x60) >> 5)) << 5); | |
| 69 | + header[12] = (byte) (header[12] | ((byte) 28)); | |
| 70 | + header[13] = (byte) (header[13] & 0xBF); | |
| 71 | + header[13] = (byte) (header[13] & 0xDF); | |
| 72 | + header[13] = (byte) (header[13] | 0x80); | |
| 73 | + header[13] = (byte) (header[13] | ((byte) (nalu[0] & 0x1F))); | |
| 74 | + buffer.put((byte) 0x24); | |
| 75 | + buffer.put((byte) 0); | |
| 76 | + buffer.putShort((short) (13 + MAX_PACKAGE_SIZE)); | |
| 77 | + buffer.put(header, 0, 2); | |
| 78 | + buffer.putShort((short) ++seq); | |
| 79 | + buffer.putInt((int) (timestamp - firstTimestamp)); | |
| 80 | + buffer.put(header, 8, 6); | |
| 81 | + buffer.put(nalu, i * MAX_PACKAGE_SIZE + 1, MAX_PACKAGE_SIZE - 1); | |
| 82 | + //System.out.println(String.format("Nalu header:%02X", nalu[0])); | |
| 83 | + //System.out.println("第一分片: " + toHex(buffer.array())); | |
| 84 | + } else if (i == group - 1) { | |
| 85 | + buffer = ByteBuffer.allocate(18 + tail); | |
| 86 | + header[1] = (byte) (header[1] | 0x80); | |
| 87 | + header[12] = (byte) (header[12] | ((byte) (nalu[0] & 0x80)) << 7); | |
| 88 | + header[12] = (byte) (header[12] | ((byte) ((nalu[0] & 0x60) >> 5)) << 5); | |
| 89 | + header[12] = (byte) (header[12] | ((byte) 28)); | |
| 90 | + header[13] = (byte) (header[13] & 0xDF); | |
| 91 | + header[13] = (byte) (header[13] & 0x7F); | |
| 92 | + header[13] = (byte) (header[13] | 0x40); | |
| 93 | + header[13] = (byte) (header[13] | ((byte) (nalu[0] & 0x1F))); | |
| 94 | + buffer.put((byte) 0x24); | |
| 95 | + buffer.put((byte) 0); | |
| 96 | + buffer.putShort((short) (14 + tail)); | |
| 97 | + buffer.put(header, 0, 2); | |
| 98 | + buffer.putShort((short) ++seq); | |
| 99 | + buffer.putInt((int) (timestamp - firstTimestamp)); | |
| 100 | + buffer.put(header, 8, 6); | |
| 101 | + buffer.put(nalu, i * MAX_PACKAGE_SIZE, tail); | |
| 102 | + //System.out.println("最后分片: " + toHex(buffer.array())); | |
| 103 | + } else { | |
| 104 | + header[1] = (byte) (header[1] & 0x7F); | |
| 105 | + header[12] = (byte) (header[12] | ((byte) (nalu[0] & 0x80)) << 7); | |
| 106 | + header[12] = (byte) (header[12] | ((byte) ((nalu[0] & 0x60) >> 5)) << 5); | |
| 107 | + header[12] = (byte) (header[12] | ((byte) 28)); | |
| 108 | + header[13] = (byte) (header[13] & 0xDF); | |
| 109 | + header[13] = (byte) (header[13] & 0x7F); | |
| 110 | + header[13] = (byte) (header[13] & 0xBF); | |
| 111 | + header[13] = (byte) (header[13] | ((byte) (nalu[0] & 0x1F))); | |
| 112 | + buffer.put((byte) 0x24); | |
| 113 | + buffer.put((byte) 0); | |
| 114 | + buffer.putShort((short) (14 + MAX_PACKAGE_SIZE)); | |
| 115 | + buffer.put(header, 0, 2); | |
| 116 | + buffer.putShort((short) ++seq); | |
| 117 | + buffer.putInt((int) (timestamp - firstTimestamp)); | |
| 118 | + buffer.put(header, 8, 6); | |
| 119 | + buffer.put(nalu, i * MAX_PACKAGE_SIZE, MAX_PACKAGE_SIZE); | |
| 120 | + //System.out.println("中间分片: " + toHex(buffer.array())); | |
| 121 | + } | |
| 122 | + streams.add(buffer.array()); | |
| 123 | + } | |
| 124 | + } | |
| 125 | + } | |
| 126 | + | |
| 127 | + return streams; | |
| 128 | + } | |
| 129 | + | |
| 130 | + public byte[] readNalu() { | |
| 131 | + for (int i = (lastPosition == 0 ? 0 : lastPosition + 1); i < buffer.length - 3; i++) { | |
| 132 | + if (buffer[i] == 0 && buffer[i + 1] == 0 && buffer[i + 2] == 0 && buffer[i + 3] == 1) { | |
| 133 | + if (i != 0) { | |
| 134 | + byte[] nalu = new byte[i - lastPosition - 4]; | |
| 135 | + System.arraycopy(buffer, lastPosition + 4, nalu, 0, i - lastPosition - 4); | |
| 136 | + lastPosition = i; | |
| 137 | + //System.out.println(toHex(nalu)); | |
| 138 | + | |
| 139 | + return nalu; | |
| 140 | + } | |
| 141 | + } | |
| 142 | + } | |
| 143 | + | |
| 144 | + return null; | |
| 145 | + } | |
| 146 | + | |
| 147 | + public String toHex(byte[] bytes) { | |
| 148 | + StringBuilder sb = new StringBuilder(); | |
| 149 | + for (byte b : bytes) { | |
| 150 | + sb.append(String.format("%02X ", b)); | |
| 151 | + } | |
| 152 | + | |
| 153 | + return sb.toString(); | |
| 154 | + } | |
| 155 | + | |
| 156 | + public static void main(String[] args) { | |
| 157 | + byte[] bytes = new byte[]{(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,(byte)0x67,(byte)0x4D,(byte)0x00,(byte)0x1F,(byte)0x96,(byte)0x35,(byte)0x41,(byte)0xE0,(byte)0x24,(byte)0xD3,(byte)0x70,(byte)0x50,(byte)0x10,(byte)0x50,(byte)0x20,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,(byte)0x68,(byte)0xEE,(byte)0x31,(byte)0xB2,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,(byte)0x06,(byte)0xE5,(byte)0x01,(byte)0x4A,(byte)0x80,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,(byte)0x65,(byte)0xB8,(byte)0x00,(byte)0x00,(byte)0x0C,(byte)0x16,(byte)0x90,(byte)0x00,(byte)0x00,(byte)0xBF,(byte)0xFE,(byte)0xD4,(byte)0xA7,(byte)0x99,(byte)0x63,(byte)0xE6,(byte)0xF9,(byte)0x5A,(byte)0x75,(byte)0xCE,(byte)0xDB,(byte)0x0C,(byte)0xD3,(byte)0xA6,(byte)0x31,(byte)0x05,(byte)0x66,(byte)0x6C,(byte)0x18,(byte)0x87,(byte)0xD0,(byte)0xF9,(byte)0xD0,(byte)0xCC,(byte)0xA3,(byte)0x57,(byte)0x07,(byte)0xDF,(byte)0x7C,(byte)0x6F,(byte)0x42,(byte)0xE9,(byte)0x8B,(byte)0x1B,(byte)0xA2,(byte)0x70,(byte)0x8C,(byte)0x80,(byte)0x00,(byte)0x00,(byte)0x1A,(byte)0xD6,(byte)0xEB,(byte)0x80,(byte)0xDE,(byte)0xE6,(byte)0xE2,(byte)0xF5,(byte)0xFF,(byte)0x33,(byte)0x98,(byte)0x97,(byte)0xCD,(byte)0xEB,(byte)0xEB,(byte)0xE5,(byte)0x60,(byte)0x00,(byte)0x00,(byte)0x0F,(byte)0xFB,(byte)0x49,(byte)0x08,(byte)0x9C,(byte)0x75,(byte)0xB4,(byte)0xDB,(byte)0xCE,(byte)0x58,(byte)0x08,(byte)0xB4,(byte)0x68,(byte)0x22,(byte)0x16,(byte)0x51,(byte)0x47,(byte)0xF3,(byte)0xD3,(byte)0x56,(byte)0xC2,(byte)0x4F,(byte)0x12,(byte)0xFD,(byte)0x2B,(byte)0xC9,(byte)0x45,(byte)0x80,(byte)0xDB,(byte)0xA4,(byte)0x62,(byte)0xEB,(byte)0xC3,(byte)0x6D,(byte)0xFE,(byte)0x36,(byte)0x20,(byte)0xAE,(byte)0xD9,(byte)0xD2,(byte)0x4C,(byte)0x9E,(byte)0x06,(byte)0xA0,(byte)0x8B,(byte)0x42,(byte)0x35,(byte)0xEC,(byte)0x64,(byte)0x03,(byte)0x22,(byte)0x29,(byte)0x26,(byte)0x19,(byte)0x70,(byte)0xCA,(byte)0x18,(byte)0xC0,(byte)0x7E,(byte)0x08,(byte)0x4F,(byte)0xEB,(byte)0xFD,(byte)0x5D,(byte)0x90,(byte)0x31,(byte)0x62,(byte)0x02,(byte)0x2E,(byte)0xBE,(byte)0x53,(byte)0xCF,(byte)0xC0,(byte)0xA8,(byte)0xAC,(byte)0xF3,(byte)0x92,(byte)0xC8,(byte)0x76,(byte)0x77,(byte)0x84,(byte)0x2F,(byte)0x76,(byte)0x45,(byte)0xF3,(byte)0xBF,(byte)0x07,(byte)0x1F,(byte)0x6D,(byte)0xC6,(byte)0x11,(byte)0xB9,(byte)0x83,(byte)0xF6,(byte)0xDF,(byte)0xA1,(byte)0x6D,(byte)0x56,(byte)0x6D,(byte)0xE0,(byte)0xFA,(byte)0xC1,(byte)0x7E,(byte)0xC5,(byte)0xC5,(byte)0x3C,(byte)0x69,(byte)0x57,(byte)0x61,(byte)0xCA,(byte)0x17,(byte)0x40,(byte)0x30,(byte)0xAE,(byte)0x4E,(byte)0x4C,(byte)0x61,(byte)0xC3,(byte)0xAF,(byte)0x6F,(byte)0xB4,(byte)0x48,(byte)0x33,(byte)0x4F,(byte)0x59,(byte)0x6D,(byte)0x88,(byte)0xA0,(byte)0x3B,(byte)0x9C,(byte)0x39,(byte)0x67,(byte)0xAD,(byte)0x0C,(byte)0xC0,(byte)0x64,(byte)0x8A,(byte)0xDB,(byte)0x95,(byte)0xB3,(byte)0xEF,(byte)0x6A,(byte)0xC0,(byte)0x9B,(byte)0xAF,(byte)0x44,(byte)0xBF,(byte)0x69,(byte)0x77,(byte)0x7D,(byte)0x2B,(byte)0xDB,(byte)0x47,(byte)0x78,(byte)0xD0,(byte)0x9C,(byte)0x79,(byte)0xA1,(byte)0xFE,(byte)0xC4,(byte)0xC4,(byte)0xAF,(byte)0x6A,(byte)0x2C,(byte)0x2D,(byte)0xF4,(byte)0xB6,(byte)0x27,(byte)0xC6,(byte)0x3C,(byte)0x71,(byte)0xC1,(byte)0x5E,(byte)0xB0,(byte)0x22,(byte)0x93,(byte)0x88,(byte)0x9C,(byte)0x98,(byte)0x3A,(byte)0x8D,(byte)0x7F,(byte)0x2E,(byte)0x48,(byte)0x53,(byte)0x2D,(byte)0xF5,(byte)0x7A,(byte)0xD0,(byte)0xC2,(byte)0x68,(byte)0xAF,(byte)0xB7,(byte)0x8C,(byte)0xF4,(byte)0xD4,(byte)0x99,(byte)0x96,(byte)0x24,(byte)0x47,(byte)0x2B,(byte)0x28,(byte)0x26,(byte)0xE4,(byte)0xBD,(byte)0xFA,(byte)0x65,(byte)0x7C,(byte)0xB3,(byte)0xA8,(byte)0x3E,(byte)0x43,(byte)0xF4,(byte)0x6D,(byte)0x50,(byte)0x7F,(byte)0xE3,(byte)0xF5,(byte)0x73,(byte)0xE6,(byte)0xF2,(byte)0x23,(byte)0x3A,(byte)0x22,(byte)0x74,(byte)0x7B,(byte)0x1E,(byte)0xDC,(byte)0xFB,(byte)0xF4,(byte)0xA8,(byte)0x97,(byte)0xB9,(byte)0x3A,(byte)0x73,(byte)0x8B,(byte)0x78,(byte)0x64,(byte)0x03,(byte)0x55,(byte)0x6E,(byte)0x52,(byte)0x7D,(byte)0x4C,(byte)0x28,(byte)0x00,(byte)0x43,(byte)0x72,(byte)0x84,(byte)0xF1,(byte)0x81,(byte)0x55,(byte)0x7B,(byte)0x8D,(byte)0x0F,(byte)0x7F,(byte)0xB4,(byte)0xEB,(byte)0xAB,(byte)0x69,(byte)0x65,(byte)0x7B,(byte)0x92,(byte)0xAC,(byte)0xB6,(byte)0xB4,(byte)0x33,(byte)0x5D,(byte)0x33,(byte)0x5D,(byte)0xC2,(byte)0xF8,(byte)0x25,(byte)0x7E,(byte)0x1D,(byte)0x1D,(byte)0xDB,(byte)0x1C,(byte)0xF8,(byte)0xBE,(byte)0x4B,(byte)0x25,(byte)0xA9,(byte)0xB5,(byte)0x8A,(byte)0x8D,(byte)0x67,(byte)0x61,(byte)0xFF,(byte)0xE3,(byte)0x18,(byte)0x1C,(byte)0x8F,(byte)0x7F,(byte)0xBA,(byte)0x50,(byte)0x47,(byte)0x10,(byte)0x5D,(byte)0xD5,(byte)0x97,(byte)0x62,(byte)0x06,(byte)0x09,(byte)0x52,(byte)0xC3,(byte)0x81,(byte)0x1A,(byte)0x58,(byte)0x87,(byte)0xFC,(byte)0x30,(byte)0x61,(byte)0x89,(byte)0xF5,(byte)0x2C,(byte)0x58,(byte)0x04,(byte)0x32,(byte)0x8B,(byte)0x3E,(byte)0x79,(byte)0xA3,(byte)0x10,(byte)0xFD,(byte)0x11,(byte)0x59,(byte)0xCA,(byte)0x08,(byte)0x48,(byte)0x24,(byte)0xDF,(byte)0x5F,(byte)0x02,(byte)0x12,(byte)0x2F,(byte)0x4C,(byte)0xDC,(byte)0xE9,(byte)0xFE,(byte)0xF0,(byte)0x21,(byte)0x5B,(byte)0xD3,(byte)0x0C,(byte)0xA7,(byte)0xF6,(byte)0xEF,(byte)0xFD,(byte)0xA4,(byte)0xB0,(byte)0xEF,(byte)0x47,(byte)0xC6,(byte)0x8F,(byte)0xB7,(byte)0x90,(byte)0xE3,(byte)0x03,(byte)0xBE,(byte)0x85,(byte)0x51,(byte)0x56,(byte)0x65,(byte)0xD3,(byte)0x6B,(byte)0xC4,(byte)0x8F,(byte)0x00,(byte)0x09,(byte)0xCC,(byte)0x0C,(byte)0x7C,(byte)0x69,(byte)0x42,(byte)0x68,(byte)0x05,(byte)0x97,(byte)0x5D,(byte)0xD8,(byte)0x66,(byte)0x8E,(byte)0x1D,(byte)0x2E,(byte)0x65,(byte)0x0B,(byte)0xCC,(byte)0x24,(byte)0x15,(byte)0xE4,(byte)0x10,(byte)0x23,(byte)0x4D,(byte)0xAE,(byte)0x01,(byte)0xCB,(byte)0xEB,(byte)0x16,(byte)0xAE,(byte)0x5A,(byte)0xA9,(byte)0xA0,(byte)0xFD,(byte)0xE8,(byte)0x62,(byte)0x57,(byte)0x8E,(byte)0x8F,(byte)0x57,(byte)0xA7,(byte)0xCC,(byte)0x6B,(byte)0xEB,(byte)0xDF,(byte)0xC1,(byte)0xBD,(byte)0xA6,(byte)0x40,(byte)0x40,(byte)0x07,(byte)0xAC,(byte)0x0A,(byte)0x40,(byte)0xD1,(byte)0xA7,(byte)0x9F,(byte)0x8D,(byte)0xE8,(byte)0x36,(byte)0xD8,(byte)0x53,(byte)0x54,(byte)0x66,(byte)0x14,(byte)0x5B,(byte)0x38,(byte)0x23,(byte)0xC5,(byte)0x72,(byte)0xA1,(byte)0x9D,(byte)0x3B,(byte)0xDD,(byte)0xD3,(byte)0xD6,(byte)0x46,(byte)0xE9,(byte)0x7D,(byte)0x0D,(byte)0xA7,(byte)0x22,(byte)0x00,(byte)0x87,(byte)0x7C,(byte)0x4E,(byte)0x4E,(byte)0x56,(byte)0xE1,(byte)0x03,(byte)0x99,(byte)0x4A,(byte)0xB5,(byte)0x09,(byte)0xD7,(byte)0xC1,(byte)0x0F,(byte)0xDD,(byte)0xB5,(byte)0x91,(byte)0xF8,(byte)0x3D,(byte)0x19,(byte)0x63,(byte)0xAD,(byte)0xC1,(byte)0x21,(byte)0x46,(byte)0x2F,(byte)0x2A,(byte)0xE8,(byte)0x11,(byte)0xFA,(byte)0x56,(byte)0xCD,(byte)0x16,(byte)0xB2,(byte)0x1C,(byte)0xA0,(byte)0xB1,(byte)0xBC,(byte)0xB4,(byte)0x99,(byte)0xBC,(byte)0xFB,(byte)0x60,(byte)0x48,(byte)0x45,(byte)0xFB,(byte)0x52,(byte)0x5A,(byte)0xE5,(byte)0x1A,(byte)0x43,(byte)0x6B,(byte)0x26,(byte)0xC3,(byte)0xD8,(byte)0xE6,(byte)0x1F,(byte)0x0F,(byte)0x1D,(byte)0x77,(byte)0x92,(byte)0xB7,(byte)0x05,(byte)0x15,(byte)0x8A,(byte)0xEE,(byte)0xB8,(byte)0x62,(byte)0x82,(byte)0x9D,(byte)0x98,(byte)0x94,(byte)0xA7,(byte)0xBA,(byte)0x7B,(byte)0x19,(byte)0x8B,(byte)0x8E,(byte)0x3F,(byte)0xB4,(byte)0x1B,(byte)0x9B,(byte)0x4D,(byte)0xD3,(byte)0xA2,(byte)0x28,(byte)0x05,(byte)0x99,(byte)0xC8,(byte)0xF7,(byte)0x2A,(byte)0x6F,(byte)0xB9,(byte)0xC9,(byte)0x96,(byte)0xF6,(byte)0x03,(byte)0xC6,(byte)0x10,(byte)0xBF,(byte)0xF2,(byte)0xD5,(byte)0xAE,(byte)0x7F,(byte)0x93,(byte)0xE4,(byte)0xB6,(byte)0x4D,(byte)0xE0,(byte)0xE5,(byte)0x06,(byte)0x4E,(byte)0x4C,(byte)0xC5,(byte)0xD5,(byte)0xD9,(byte)0xF8,(byte)0x1E,(byte)0x36,(byte)0x38,(byte)0x01,(byte)0x7C,(byte)0xBC,(byte)0x1C,(byte)0x71,(byte)0x46,(byte)0x2C,(byte)0xCE,(byte)0xBD,(byte)0x23,(byte)0x14,(byte)0x37,(byte)0xBB,(byte)0x70,(byte)0xC6,(byte)0x7A,(byte)0xF7,(byte)0x73,(byte)0xA8,(byte)0xA9,(byte)0xDC,(byte)0xC2,(byte)0xC0,(byte)0x7A,(byte)0xDA,(byte)0x74,(byte)0xFF,(byte)0x25,(byte)0x73,(byte)0x31,(byte)0xD8,(byte)0xF9,(byte)0x4D,(byte)0x66,(byte)0xD3,(byte)0x5E,(byte)0x98,(byte)0xC6,(byte)0xC4,(byte)0x55,(byte)0x0B,(byte)0xC4,(byte)0xB1,(byte)0xED,(byte)0x0F,(byte)0x74,(byte)0x5D,(byte)0x1B,(byte)0x7A,(byte)0x05,(byte)0xDB,(byte)0x7C,(byte)0x0D,(byte)0xDF,(byte)0xE2,(byte)0x6B,(byte)0xAF,(byte)0x22,(byte)0x3B,(byte)0x11,(byte)0x35,(byte)0xE3,(byte)0x51,(byte)0x13,(byte)0x07,(byte)0xD3,(byte)0x6E,(byte)0xAE,(byte)0x91,(byte)0xE2,(byte)0x98,(byte)0x02,(byte)0x6D,(byte)0xD9,(byte)0xD9,(byte)0xBD,(byte)0x7C,(byte)0x8E,(byte)0xBF,(byte)0xBE,(byte)0xB7,(byte)0x79,(byte)0xCA,(byte)0xC1,(byte)0x66,(byte)0x89,(byte)0x17,(byte)0x9B,(byte)0x77,(byte)0xBE,(byte)0xA7,(byte)0xED,(byte)0x3E,(byte)0xCC,(byte)0x86,(byte)0x44,(byte)0x42,(byte)0x38,(byte)0x50,(byte)0x8D,(byte)0xC3,(byte)0x58,(byte)0x07,(byte)0x42,(byte)0xBF,(byte)0x7C,(byte)0xC3,(byte)0x72,(byte)0x81,(byte)0x6E,(byte)0xFC,(byte)0xC8,(byte)0x63,(byte)0x8B,(byte)0x2E,(byte)0x63,(byte)0xA6,(byte)0x17,(byte)0x62,(byte)0x3C,(byte)0xED,(byte)0x29,(byte)0xFE,(byte)0xBC,(byte)0x4E,(byte)0x8B,(byte)0x94,(byte)0x4B,(byte)0x46,(byte)0xE6,(byte)0xC7,(byte)0x1A,(byte)0x32,(byte)0xE7,(byte)0xC8,(byte)0x44,(byte)0x47,(byte)0x1C,(byte)0xE8,(byte)0xC7,(byte)0x8C,(byte)0x1F,(byte)0x9E,(byte)0x16,(byte)0xED,(byte)0x12,(byte)0x8D,(byte)0x66,(byte)0x71,(byte)0xF4,(byte)0x1E,(byte)0x22,(byte)0xAB,(byte)0xD9,(byte)0xF5,(byte)0x22,(byte)0xC3,(byte)0x31,(byte)0x0B,(byte)0xD6,(byte)0x12,(byte)0x46,(byte)0x99,(byte)0x13,(byte)0xD2,(byte)0x02,(byte)0x34,(byte)0x7E,(byte)0x01,(byte)0x25,(byte)0xAC,(byte)0xB6,(byte)0xF1,(byte)0xF1,(byte)0x46,(byte)0xBE,(byte)0x90,(byte)0x79,(byte)0xBA,(byte)0x5B,(byte)0x36,(byte)0xF7,(byte)0x81,(byte)0x70,(byte)0x4A,(byte)0xDC,(byte)0xF1,(byte)0x24,(byte)0x9A,(byte)0x87,(byte)0x1E,(byte)0x59,(byte)0xE1,(byte)0x46,(byte)0xDC,(byte)0x0E,(byte)0x71,(byte)0xB4,(byte)0xE5,(byte)0x48,(byte)0x0E,(byte)0x11,(byte)0x87,(byte)0x99,(byte)0x2A,(byte)0x5C,(byte)0x61,(byte)0x75,(byte)0x3C,(byte)0x5B,(byte)0xF8,(byte)0xE6,(byte)0xE4,(byte)0x01,(byte)0xA2,(byte)0x01,(byte)0xE5,(byte)0x79,(byte)0x52,(byte)0x0B,(byte)0xC7,(byte)0xF7,(byte)0xED,(byte)0x0B,(byte)0x52,(byte)0x47,(byte)0x77,(byte)0xAD,(byte)0x45,(byte)0x72,(byte)0x21,(byte)0x0E,(byte)0xBE,(byte)0xA5,(byte)0x3D,(byte)0xEA,(byte)0xBF,(byte)0x44,(byte)0x7E,(byte)0x75,(byte)0x8C,(byte)0xF0,(byte)0x05,(byte)0xBB,(byte)0xDD,(byte)0xE3,(byte)0x53,(byte)0x4E,(byte)0x1B,(byte)0xB4,(byte)0x2F,(byte)0x65,(byte)0xCE,(byte)0x44,(byte)0x95,(byte)0x4F,(byte)0x44,(byte)0x1D,(byte)0x0D,(byte)0x54,(byte)0xF9,(byte)0xCD,(byte)0x30,(byte)0x00,(byte)0x81,(byte)0x2C,(byte)0x5C,(byte)0xFF,(byte)0xBE}; | |
| 158 | + H264Packeter packeter = new H264Packeter(); | |
| 159 | + packeter.packet(bytes, 0); | |
| 160 | + } | |
| 161 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/rtsp/RtspRequest.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/rtsp/RtspRequest.java | |
| 1 | +package cn.org.hentai.jtt1078.rtsp; | |
| 2 | + | |
| 3 | +import io.netty.handler.codec.http.DefaultFullHttpRequest; | |
| 4 | +import io.netty.handler.codec.http.FullHttpRequest; | |
| 5 | +import io.netty.handler.codec.rtsp.RtspHeaderNames; | |
| 6 | +import io.netty.handler.codec.rtsp.RtspMethods; | |
| 7 | +import io.netty.handler.codec.rtsp.RtspVersions; | |
| 8 | +import io.netty.util.internal.StringUtil; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * Rtsp请求 | |
| 12 | + */ | |
| 13 | +public class RtspRequest { | |
| 14 | + | |
| 15 | + private final String CRLF = "\r\n"; | |
| 16 | + | |
| 17 | + private final String VERSION = "RTSP/1.0"; | |
| 18 | + | |
| 19 | + private int seq = 0; | |
| 20 | + | |
| 21 | + private String host; | |
| 22 | + | |
| 23 | + private int port; | |
| 24 | + | |
| 25 | + private String path; | |
| 26 | + | |
| 27 | + private String sessionID; | |
| 28 | + | |
| 29 | + public RtspRequest(String host, int port, String path) { | |
| 30 | + this.host = host; | |
| 31 | + this.port = port; | |
| 32 | + this.path = path; | |
| 33 | + } | |
| 34 | + | |
| 35 | + public String getHost() { | |
| 36 | + return host; | |
| 37 | + } | |
| 38 | + | |
| 39 | + public void setHost(String host) { | |
| 40 | + this.host = host; | |
| 41 | + } | |
| 42 | + | |
| 43 | + public int getPort() { | |
| 44 | + return port; | |
| 45 | + } | |
| 46 | + | |
| 47 | + public void setPort(int port) { | |
| 48 | + this.port = port; | |
| 49 | + } | |
| 50 | + | |
| 51 | + public String getPath() { | |
| 52 | + return path; | |
| 53 | + } | |
| 54 | + | |
| 55 | + public void setPath(String path) { | |
| 56 | + this.path = path; | |
| 57 | + } | |
| 58 | + | |
| 59 | + public String getSessionID() { | |
| 60 | + return sessionID; | |
| 61 | + } | |
| 62 | + | |
| 63 | + public void setSessionID(String sessionID) { | |
| 64 | + this.sessionID = sessionID; | |
| 65 | + } | |
| 66 | + | |
| 67 | + public FullHttpRequest option() { | |
| 68 | + FullHttpRequest request = new DefaultFullHttpRequest(RtspVersions.RTSP_1_0, RtspMethods.OPTIONS, String.format("rtsp://%s:%d%s", host, port, path)); | |
| 69 | + request.headers().set(RtspHeaderNames.CSEQ, ++seq); | |
| 70 | + | |
| 71 | + return request; | |
| 72 | + } | |
| 73 | + | |
| 74 | + public FullHttpRequest announce() { | |
| 75 | + StringBuilder body = new StringBuilder(); | |
| 76 | + FullHttpRequest request = new DefaultFullHttpRequest(RtspVersions.RTSP_1_0, RtspMethods.ANNOUNCE, String.format("rtsp://%s:%d%s", host, port, path)); | |
| 77 | + request.headers().set(RtspHeaderNames.CSEQ, ++seq); | |
| 78 | + request.headers().set(RtspHeaderNames.CONTENT_TYPE, "application/sdp"); | |
| 79 | + | |
| 80 | + body.append("v=0").append(CRLF) | |
| 81 | + .append("o=- 0 0 IN IP4 127.0.0.1").append(CRLF) | |
| 82 | + .append("s=No Name").append(CRLF) | |
| 83 | + .append("c=IN IP4 ").append(this.host).append(CRLF) | |
| 84 | + .append("t=0 0").append(CRLF) | |
| 85 | + .append("a=tool:libavformat 61.9.100").append(CRLF) | |
| 86 | + .append("m=video 0 RTP/AVP 96").append(CRLF) | |
| 87 | + .append("b=AS:3943").append(CRLF) | |
| 88 | + .append("a=rtpmap:96 H264/90000").append(CRLF) | |
| 89 | + .append("a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z00AKp2oHgCJ+WbgICAoAAADAAgAAAMBlCA=,aO48gA==; profile-level-id=4D002A").append(CRLF) | |
| 90 | + .append("a=control:streamid=0").append(CRLF); | |
| 91 | + request.content().writeBytes(body.toString().getBytes()); | |
| 92 | + request.headers().set(RtspHeaderNames.CONTENT_LENGTH, body.toString().getBytes().length); | |
| 93 | + | |
| 94 | + return request; | |
| 95 | + } | |
| 96 | + | |
| 97 | + public FullHttpRequest setup() { | |
| 98 | + FullHttpRequest request = new DefaultFullHttpRequest(RtspVersions.RTSP_1_0, RtspMethods.SETUP, String.format("rtsp://%s:%d%s/streamid=0", host, port, path)); | |
| 99 | + request.headers().set(RtspHeaderNames.CSEQ, ++seq); | |
| 100 | + request.headers().set(RtspHeaderNames.TRANSPORT, "RTP/AVP/TCP;unicast;interleaved=0-1;mode=record"); | |
| 101 | + request.headers().set(RtspHeaderNames.SESSION, sessionID); | |
| 102 | + | |
| 103 | + return request; | |
| 104 | + } | |
| 105 | + | |
| 106 | + public FullHttpRequest record() { | |
| 107 | + FullHttpRequest request = new DefaultFullHttpRequest(RtspVersions.RTSP_1_0, RtspMethods.RECORD, String.format("rtsp://%s:%d%s/streamid=0", host, port, path)); | |
| 108 | + request.headers().set(RtspHeaderNames.CSEQ, ++seq); | |
| 109 | + request.headers().set(RtspHeaderNames.RANGE, "npt=0.000-"); | |
| 110 | + request.headers().set(RtspHeaderNames.SESSION, sessionID); | |
| 111 | + | |
| 112 | + return request; | |
| 113 | + } | |
| 114 | + | |
| 115 | + public String teardown() { | |
| 116 | + StringBuilder sb = new StringBuilder(); | |
| 117 | + | |
| 118 | + return sb.toString(); | |
| 119 | + } | |
| 120 | + | |
| 121 | + private String header(int length) { | |
| 122 | + StringBuilder sb = new StringBuilder(); | |
| 123 | + | |
| 124 | + return sb.append("CSeq: ").append(++seq).append(CRLF) | |
| 125 | + .append("User-Agent: jt1078").append(CRLF) | |
| 126 | + .append("Content-Length: ").append(length).append(CRLF) | |
| 127 | + .append(StringUtil.isNullOrEmpty(sessionID) ? "" : "Session: ").append(StringUtil.isNullOrEmpty(sessionID) ? "" : sessionID).append(StringUtil.isNullOrEmpty(sessionID) ? "" : CRLF).append(CRLF).toString(); | |
| 128 | + } | |
| 129 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/rtsp/RtspSessionManager.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/rtsp/RtspSessionManager.java | |
| 1 | +package cn.org.hentai.jtt1078.rtsp; | |
| 2 | + | |
| 3 | +import io.netty.channel.Channel; | |
| 4 | + | |
| 5 | +import java.util.Map; | |
| 6 | +import java.util.concurrent.ConcurrentHashMap; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * Rtsp会话 | |
| 10 | + */ | |
| 11 | +public class RtspSessionManager { | |
| 12 | + | |
| 13 | + private static Map<String, Object> channel2register = new ConcurrentHashMap<>(); | |
| 14 | + | |
| 15 | + private static Map<String, Channel> channel2push = new ConcurrentHashMap<>(); | |
| 16 | + | |
| 17 | + public static void register(String channel) { | |
| 18 | + channel2register.put(channel, System.currentTimeMillis()); | |
| 19 | + } | |
| 20 | + | |
| 21 | + public static void unregister(String channel) { | |
| 22 | + channel2register.remove(channel); | |
| 23 | + } | |
| 24 | + | |
| 25 | + public static boolean isRegistered(String channel) { | |
| 26 | + return channel2register.containsKey(channel); | |
| 27 | + } | |
| 28 | + | |
| 29 | + public static void setPush(String channel, Channel push) { | |
| 30 | + channel2push.put(channel, push); | |
| 31 | + } | |
| 32 | + | |
| 33 | + public static Channel getPush(String channel) { | |
| 34 | + return channel2push.get(channel); | |
| 35 | + } | |
| 36 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Decoder.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Decoder.java | |
| 1 | +package cn.org.hentai.jtt1078.server; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.util.ByteHolder; | |
| 4 | +import cn.org.hentai.jtt1078.util.ByteUtils; | |
| 5 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * Created by matrixy on 2019/4/9. | |
| 9 | + */ | |
| 10 | +public class Jtt1078Decoder | |
| 11 | +{ | |
| 12 | + ByteHolder buffer = new ByteHolder(4096); | |
| 13 | + | |
| 14 | + public void write(byte[] block) | |
| 15 | + { | |
| 16 | + buffer.write(block); | |
| 17 | + } | |
| 18 | + | |
| 19 | + public void write(byte[] block, int startIndex, int length) | |
| 20 | + { | |
| 21 | + byte[] buff = new byte[length]; | |
| 22 | + System.arraycopy(block, startIndex, buff, 0, length); | |
| 23 | + write(buff); | |
| 24 | + } | |
| 25 | + | |
| 26 | + public Packet decode() | |
| 27 | + { | |
| 28 | + if (this.buffer.size() < 30) return null; | |
| 29 | + | |
| 30 | + if ((buffer.getInt(0) & 0x7fffffff) != 0x30316364) | |
| 31 | + { | |
| 32 | + String header = ByteUtils.toString(buffer.array(30)); | |
| 33 | + throw new RuntimeException("invalid protocol header: " + header); | |
| 34 | + } | |
| 35 | + | |
| 36 | + int lengthOffset = 28; | |
| 37 | + int dataType = (this.buffer.get(15) >> 4) & 0x0f; | |
| 38 | + // 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段 | |
| 39 | + if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; | |
| 40 | + else if (dataType == 0x03) lengthOffset = 28 - 4; | |
| 41 | + int bodyLength = this.buffer.getShort(lengthOffset); | |
| 42 | + | |
| 43 | + int packetLength = bodyLength + lengthOffset + 2; | |
| 44 | + | |
| 45 | + if (this.buffer.size() < packetLength) return null; | |
| 46 | + byte[] block = new byte[packetLength]; | |
| 47 | + this.buffer.sliceInto(block, packetLength); | |
| 48 | + return Packet.create(block); | |
| 49 | + } | |
| 50 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Handler.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078Handler.java | |
| 1 | +package cn.org.hentai.jtt1078.server; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.publisher.Channel; | |
| 4 | +import cn.org.hentai.jtt1078.publisher.PublishManager; | |
| 5 | +import cn.org.hentai.jtt1078.rtp.H264Packeter; | |
| 6 | +import cn.org.hentai.jtt1078.rtsp.RtspSessionManager; | |
| 7 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 8 | +import io.netty.bootstrap.Bootstrap; | |
| 9 | +import io.netty.buffer.Unpooled; | |
| 10 | +import io.netty.channel.*; | |
| 11 | +import io.netty.channel.nio.NioEventLoopGroup; | |
| 12 | +import io.netty.channel.socket.SocketChannel; | |
| 13 | +import io.netty.channel.socket.nio.NioSocketChannel; | |
| 14 | +import io.netty.handler.codec.rtsp.RtspDecoder; | |
| 15 | +import io.netty.handler.codec.rtsp.RtspEncoder; | |
| 16 | +import io.netty.util.AttributeKey; | |
| 17 | +import org.slf4j.Logger; | |
| 18 | +import org.slf4j.LoggerFactory; | |
| 19 | +import io.netty.handler.timeout.IdleState; | |
| 20 | +import io.netty.handler.timeout.IdleStateEvent; | |
| 21 | + | |
| 22 | +import java.net.InetSocketAddress; | |
| 23 | + | |
| 24 | +/** | |
| 25 | + * Created by matrixy on 2019/4/9. | |
| 26 | + */ | |
| 27 | +public class Jtt1078Handler extends SimpleChannelInboundHandler<Packet> | |
| 28 | +{ | |
| 29 | + static Logger logger = LoggerFactory.getLogger(Jtt1078Handler.class); | |
| 30 | + private static final AttributeKey<Session> SESSION_KEY = AttributeKey.valueOf("session-key"); | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + protected void channelRead0(ChannelHandlerContext ctx, Packet packet) throws Exception | |
| 34 | + { | |
| 35 | + io.netty.channel.Channel nettyChannel = ctx.channel(); | |
| 36 | + | |
| 37 | + packet.seek(8); | |
| 38 | + String sim = packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD() + packet.nextBCD(); | |
| 39 | + int channel = packet.nextByte() & 0xff; | |
| 40 | + String tag = sim + "-" + channel; | |
| 41 | + | |
| 42 | + if (SessionManager.contains(nettyChannel, "tag") == false) { | |
| 43 | + Channel chl = PublishManager.getInstance().open(tag); | |
| 44 | + SessionManager.set(nettyChannel, "tag", tag); | |
| 45 | + new Thread(new PushTask(tag)).start(); | |
| 46 | + logger.info("start publishing: {} -> {}-{}", Long.toHexString(chl.hashCode() & 0xffffffffL), sim, channel); | |
| 47 | + } | |
| 48 | + | |
| 49 | + Integer sequence = SessionManager.get(nettyChannel, "video-sequence"); | |
| 50 | + if (sequence == null) sequence = 0; | |
| 51 | + // 1. 做好序号 | |
| 52 | + // 2. 音频需要转码后提供订阅 | |
| 53 | + int lengthOffset = 28; | |
| 54 | + int dataType = (packet.seek(15).nextByte() >> 4) & 0x0f; | |
| 55 | + int pkType = packet.seek(15).nextByte() & 0x0f; | |
| 56 | + // 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段 | |
| 57 | + if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; | |
| 58 | + else if (dataType == 0x03) lengthOffset = 28 - 4; | |
| 59 | + | |
| 60 | + int pt = packet.seek(5).nextByte() & 0x7f; | |
| 61 | + | |
| 62 | + if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) | |
| 63 | + { | |
| 64 | + // 碰到结束标记时,序号+1 | |
| 65 | + if (pkType == 0 || pkType == 2) | |
| 66 | + { | |
| 67 | + sequence += 1; | |
| 68 | + SessionManager.set(nettyChannel, "video-sequence", sequence); | |
| 69 | + } | |
| 70 | + long timestamp = packet.seek(16).nextLong(); | |
| 71 | + //PublishManager.getInstance().publishVideo(tag, sequence, timestamp, pt, packet.seek(lengthOffset + 2).nextBytes()); | |
| 72 | + if (RtspSessionManager.isRegistered(tag)) { | |
| 73 | + io.netty.channel.Channel push = RtspSessionManager.getPush(tag); | |
| 74 | + H264Packeter packeter = (H264Packeter) push.attr(AttributeKey.valueOf(tag)).get(); | |
| 75 | + for (byte[] nalu : packeter.packet(packet.seek(lengthOffset + 2).nextBytes(), timestamp)) { | |
| 76 | + push.writeAndFlush(Unpooled.wrappedBuffer(nalu)); | |
| 77 | + } | |
| 78 | + } | |
| 79 | + } | |
| 80 | + else if (dataType == 0x03) | |
| 81 | + { | |
| 82 | + long timestamp = packet.seek(16).nextLong(); | |
| 83 | + byte[] data = packet.seek(lengthOffset + 2).nextBytes(); | |
| 84 | + PublishManager.getInstance().publishAudio(tag, sequence, timestamp, pt, data); | |
| 85 | + } | |
| 86 | + } | |
| 87 | + | |
| 88 | + @Override | |
| 89 | + public void channelInactive(ChannelHandlerContext ctx) throws Exception | |
| 90 | + { | |
| 91 | + super.channelInactive(ctx); | |
| 92 | + release(ctx.channel()); | |
| 93 | + } | |
| 94 | + | |
| 95 | + @Override | |
| 96 | + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception | |
| 97 | + { | |
| 98 | + // super.exceptionCaught(ctx, cause); | |
| 99 | + cause.printStackTrace(); | |
| 100 | + release(ctx.channel()); | |
| 101 | + ctx.close(); | |
| 102 | + } | |
| 103 | + | |
| 104 | + @Override | |
| 105 | + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { | |
| 106 | + if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) { | |
| 107 | + IdleStateEvent event = (IdleStateEvent) evt; | |
| 108 | + if (event.state() == IdleState.READER_IDLE) { | |
| 109 | + String tag = SessionManager.get(ctx.channel(), "tag"); | |
| 110 | + logger.info("read timeout: {}",tag); | |
| 111 | + release(ctx.channel()); | |
| 112 | + } | |
| 113 | + } | |
| 114 | + } | |
| 115 | + | |
| 116 | + private void release(io.netty.channel.Channel channel) | |
| 117 | + { | |
| 118 | + String tag = SessionManager.get(channel, "tag"); | |
| 119 | + if (tag != null) | |
| 120 | + { | |
| 121 | + logger.info("close netty channel: {}", tag); | |
| 122 | + PublishManager.getInstance().close(tag); | |
| 123 | + } | |
| 124 | + } | |
| 125 | + | |
| 126 | + static class PushTask implements Runnable { | |
| 127 | + | |
| 128 | + private String channelId; | |
| 129 | + | |
| 130 | + private H264Packeter packeter = new H264Packeter(); | |
| 131 | + | |
| 132 | + public PushTask(String channelId) { | |
| 133 | + this.channelId = channelId; | |
| 134 | + } | |
| 135 | + | |
| 136 | + @Override | |
| 137 | + public void run() { | |
| 138 | + EventLoopGroup group = new NioEventLoopGroup(); | |
| 139 | + try { | |
| 140 | + ChannelFuture future = null; | |
| 141 | + Bootstrap clientBootstrap = new Bootstrap(); | |
| 142 | + clientBootstrap.group(group) | |
| 143 | + .option(ChannelOption.TCP_NODELAY, true) | |
| 144 | + .channel(NioSocketChannel.class) | |
| 145 | + .remoteAddress(new InetSocketAddress("192.168.169.100", 9555)) | |
| 146 | + .handler(new ChannelInitializer<SocketChannel>() { | |
| 147 | + @Override | |
| 148 | + protected void initChannel(SocketChannel socketChannel) { | |
| 149 | + socketChannel.pipeline() | |
| 150 | + .addLast(new RtspEncoder()) | |
| 151 | + .addLast(new RtspDecoder()) | |
| 152 | + .addLast(new RTSPHandler()); | |
| 153 | + } | |
| 154 | + }); | |
| 155 | + while (true) { | |
| 156 | + logger.info("Waiting for server connection"); | |
| 157 | + future = clientBootstrap.connect(); | |
| 158 | + future.awaitUninterruptibly(); | |
| 159 | + if (future.isSuccess()) { | |
| 160 | + logger.info("RTSP Connection success!"); | |
| 161 | + break; | |
| 162 | + } | |
| 163 | + Thread.sleep(1000); | |
| 164 | + } | |
| 165 | + | |
| 166 | + future.channel().attr(AttributeKey.valueOf(this.channelId)).set(this.packeter); | |
| 167 | + RtspSessionManager.setPush(this.channelId, future.channel()); | |
| 168 | + // Wait for the server to close the connection. | |
| 169 | + //future.channel().closeFuture().sync(); | |
| 170 | + } catch (Exception e) { | |
| 171 | + logger.error("Error ->", e); | |
| 172 | + logger.error("<- Error"); | |
| 173 | + } | |
| 174 | + } | |
| 175 | + } | |
| 176 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/server/Jtt1078MessageDecoder.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/server/Jtt1078MessageDecoder.java | |
| 1 | +package cn.org.hentai.jtt1078.server; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.util.ByteUtils; | |
| 4 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 5 | +import io.netty.buffer.ByteBuf; | |
| 6 | +import io.netty.channel.ChannelHandlerContext; | |
| 7 | +import io.netty.handler.codec.ByteToMessageDecoder; | |
| 8 | +import org.slf4j.Logger; | |
| 9 | +import org.slf4j.LoggerFactory; | |
| 10 | + | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * Created by matrixy on 2019/4/9. | |
| 15 | + */ | |
| 16 | +public class Jtt1078MessageDecoder extends ByteToMessageDecoder | |
| 17 | +{ | |
| 18 | + static Logger logger = LoggerFactory.getLogger(Jtt1078MessageDecoder.class); | |
| 19 | + byte[] block = new byte[4096]; | |
| 20 | + Jtt1078Decoder decoder = new Jtt1078Decoder(); | |
| 21 | + | |
| 22 | + @Override | |
| 23 | + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception | |
| 24 | + { | |
| 25 | + int length = in.readableBytes(); | |
| 26 | + while (length > 30) { | |
| 27 | + in.markReaderIndex(); | |
| 28 | + int frameHeader = in.readInt(); | |
| 29 | + if (frameHeader == 0x30316364) { | |
| 30 | + in.skipBytes(11); | |
| 31 | + int dataType = (in.readByte() >> 4) & 0xFF, lengthOffset = 28; | |
| 32 | + // 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段 | |
| 33 | + if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; | |
| 34 | + else if (dataType == 0x03) lengthOffset = 28 - 4; | |
| 35 | + in.skipBytes(lengthOffset - 16); | |
| 36 | + int bodyLength = in.readShort() & 0xFFFFFFFF; | |
| 37 | + int packetLength = lengthOffset + bodyLength + 2; | |
| 38 | + //System.out.println(bodyLength); | |
| 39 | + if (length < packetLength) { | |
| 40 | + in.resetReaderIndex(); | |
| 41 | + return; | |
| 42 | + } | |
| 43 | + byte[] data = new byte[packetLength]; | |
| 44 | + in.resetReaderIndex(); | |
| 45 | + in.readBytes(data); | |
| 46 | + Packet packet = Packet.create(data); | |
| 47 | + out.add(packet); | |
| 48 | +// System.out.println("start:" + (lengthOffset + 2)); | |
| 49 | +// System.out.println(toHex(data)); | |
| 50 | + } else { | |
| 51 | + in.resetReaderIndex(); | |
| 52 | + in.readByte(); | |
| 53 | + } | |
| 54 | + | |
| 55 | + length = in.readableBytes(); | |
| 56 | + } | |
| 57 | + } | |
| 58 | + | |
| 59 | + public String toHex(byte[] bytes) { | |
| 60 | + StringBuilder sb = new StringBuilder(); | |
| 61 | + for (byte b : bytes) { | |
| 62 | + sb.append(String.format("%02X ", b)); | |
| 63 | + } | |
| 64 | + | |
| 65 | + return sb.toString(); | |
| 66 | + } | |
| 67 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/server/RTSPHandler.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/server/RTSPHandler.java | |
| 1 | +package cn.org.hentai.jtt1078.server; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.rtsp.RtspRequest; | |
| 4 | +import cn.org.hentai.jtt1078.rtsp.RtspSessionManager; | |
| 5 | +import io.netty.bootstrap.Bootstrap; | |
| 6 | +import io.netty.buffer.ByteBuf; | |
| 7 | +import io.netty.channel.*; | |
| 8 | +import io.netty.channel.nio.NioEventLoopGroup; | |
| 9 | +import io.netty.channel.socket.SocketChannel; | |
| 10 | +import io.netty.channel.socket.nio.NioSocketChannel; | |
| 11 | +import io.netty.handler.codec.http.*; | |
| 12 | +import io.netty.handler.codec.rtsp.*; | |
| 13 | +import io.netty.util.internal.StringUtil; | |
| 14 | +import org.slf4j.Logger; | |
| 15 | +import org.slf4j.LoggerFactory; | |
| 16 | + | |
| 17 | +import java.net.InetSocketAddress; | |
| 18 | +import java.util.*; | |
| 19 | + | |
| 20 | +public class RTSPHandler extends ChannelInboundHandlerAdapter { | |
| 21 | + | |
| 22 | + private final static Logger log = LoggerFactory.getLogger(RTSPHandler.class); | |
| 23 | + | |
| 24 | + private String channelId = "138000099998-1"; | |
| 25 | + | |
| 26 | + private HttpMethod currentMethod = RtspMethods.OPTIONS; | |
| 27 | + | |
| 28 | + private List<HttpMethod> methods = Arrays.asList(RtspMethods.OPTIONS, RtspMethods.ANNOUNCE, RtspMethods.SETUP, RtspMethods.RECORD, null); | |
| 29 | + | |
| 30 | + private RtspRequest rtspRequest = new RtspRequest("192.168.169.100", 9555, String.format("/schedule/%s?sign=41db35390ddad33f83944f44b8b75ded", channelId)); | |
| 31 | + | |
| 32 | + /* | |
| 33 | + When notified that the channel is active, sends a message. A channel is active | |
| 34 | + when a connection has been established, so the method is invoked when the connections | |
| 35 | + is established. | |
| 36 | + */ | |
| 37 | + @Override | |
| 38 | + public void channelActive(final ChannelHandlerContext ctx) { | |
| 39 | + log.debug("channelActive, connection established: {}", ctx); | |
| 40 | + log.debug("Sending request to the server"); | |
| 41 | + ctx.writeAndFlush(rtspRequest.option()); | |
| 42 | + } | |
| 43 | + | |
| 44 | + @Override | |
| 45 | + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { | |
| 46 | + log.info("exceptionCaught: {}", cause); | |
| 47 | + ctx.close(); | |
| 48 | + } | |
| 49 | + | |
| 50 | + @Override | |
| 51 | + public void channelRead(ChannelHandlerContext ctx, Object msg) { | |
| 52 | + log.info("Received from RTSP Server: {}", ctx); | |
| 53 | + log.info("Received from RTSP msg: {}", msg.toString()); | |
| 54 | + log.debug("Received Class Type: {}", msg.getClass().getTypeName()); | |
| 55 | + if (msg instanceof DefaultHttpResponse) { | |
| 56 | + DefaultHttpResponse res = (DefaultHttpResponse) msg; | |
| 57 | + if (RtspResponseStatuses.OK.equals(res.status())) { | |
| 58 | + log.debug("{}: {}", currentMethod, res.status()); | |
| 59 | + if (res.headers().contains(RtspHeaderNames.SESSION)) { | |
| 60 | + rtspRequest.setSessionID(res.headers().get(RtspHeaderNames.SESSION)); | |
| 61 | + } | |
| 62 | + nextMethod(ctx); | |
| 63 | + } else { | |
| 64 | + ctx.close(); | |
| 65 | + } | |
| 66 | + } else if (msg instanceof DefaultHttpContent) { | |
| 67 | + DefaultHttpContent content = (DefaultHttpContent) msg; | |
| 68 | + log.info("Content: {}", content); | |
| 69 | + | |
| 70 | + ByteBuf byteBuf = content.content(); | |
| 71 | + } else { | |
| 72 | + log.debug("dataType error: {}", msg.getClass().getTypeName()); | |
| 73 | + } | |
| 74 | + } | |
| 75 | + | |
| 76 | + private void nextMethod(ChannelHandlerContext ctx) { | |
| 77 | + for (int i = 0;i < methods.size(); i++) { | |
| 78 | + if (methods.get(i).equals(currentMethod) && i < methods.size() - 1) { | |
| 79 | + currentMethod = methods.get(i + 1); | |
| 80 | + break; | |
| 81 | + } | |
| 82 | + } | |
| 83 | + if (currentMethod == null) { | |
| 84 | + RtspSessionManager.register(channelId); | |
| 85 | + return; | |
| 86 | + } | |
| 87 | + if (currentMethod == RtspMethods.ANNOUNCE) { | |
| 88 | + ctx.writeAndFlush(rtspRequest.announce()); | |
| 89 | + } | |
| 90 | + if (currentMethod == RtspMethods.SETUP) { | |
| 91 | + ctx.writeAndFlush(rtspRequest.setup()); | |
| 92 | + } | |
| 93 | + if (currentMethod == RtspMethods.RECORD) { | |
| 94 | + ctx.writeAndFlush(rtspRequest.record()); | |
| 95 | + } | |
| 96 | + } | |
| 97 | + | |
| 98 | + private void parseSdp(String sdp) { | |
| 99 | + log.debug("Parsing SDP: {}", sdp); | |
| 100 | + Map<String, List<String>> mediaMap = new HashMap<>(10); | |
| 101 | + String[] array = sdp.split("\\n"); | |
| 102 | + String mediaName = ""; | |
| 103 | + for (int i = 0; i < array.length; i++) { | |
| 104 | + String line = array[i]; | |
| 105 | + if (line.startsWith("m=")) { | |
| 106 | + mediaName = line.substring(line.indexOf("=") + 1, line.indexOf(" ")); | |
| 107 | + if (mediaName.equals("video") || mediaName.equals("audio")) { | |
| 108 | + mediaMap.put(mediaName, new ArrayList<>()); | |
| 109 | + } else { | |
| 110 | + mediaName = ""; | |
| 111 | + } | |
| 112 | + } else if (!StringUtil.isNullOrEmpty(mediaName)) { | |
| 113 | + if (line.startsWith("b=") || line.startsWith("a=")) { | |
| 114 | + List<String> medialist = mediaMap.get(mediaName); | |
| 115 | + medialist.add(line); | |
| 116 | + } | |
| 117 | + } | |
| 118 | + } | |
| 119 | + for (String mediaKey : mediaMap.keySet()) { | |
| 120 | + StringBuilder stringBuilder = new StringBuilder(); | |
| 121 | + List<String> mediaInfo = mediaMap.get(mediaKey); | |
| 122 | + mediaInfo.forEach((s) -> { | |
| 123 | + stringBuilder.append("\n"); | |
| 124 | + stringBuilder.append(s); | |
| 125 | + }); | |
| 126 | + log.info("[>>>>> {} <<<<<] {}", mediaKey, stringBuilder.toString()); | |
| 127 | + } | |
| 128 | + } | |
| 129 | + | |
| 130 | + public static void main(String[] args) { | |
| 131 | + EventLoopGroup group = new NioEventLoopGroup(); | |
| 132 | + try { | |
| 133 | + Bootstrap clientBootstrap = new Bootstrap(); | |
| 134 | + clientBootstrap.group(group) | |
| 135 | + .option(ChannelOption.TCP_NODELAY, true) | |
| 136 | + .channel(NioSocketChannel.class) | |
| 137 | + .remoteAddress(new InetSocketAddress("192.168.169.100", 9555)) | |
| 138 | + .handler(new ChannelInitializer<SocketChannel>() { | |
| 139 | + @Override | |
| 140 | + protected void initChannel(SocketChannel socketChannel) { | |
| 141 | + socketChannel.pipeline() | |
| 142 | + .addLast(new RtspEncoder()) | |
| 143 | + .addLast(new RtspDecoder()) | |
| 144 | + .addLast(new RTSPHandler()); | |
| 145 | + } | |
| 146 | + }); | |
| 147 | + ChannelFuture f = null; | |
| 148 | + while (true) { | |
| 149 | + log.info("Waiting for server connection"); | |
| 150 | + f = clientBootstrap.connect(); | |
| 151 | + f.awaitUninterruptibly(); | |
| 152 | + if (f.isSuccess()) { | |
| 153 | + log.info("RTSP Connection success!"); | |
| 154 | + break; | |
| 155 | + } | |
| 156 | + Thread.sleep(1000); | |
| 157 | + } | |
| 158 | + | |
| 159 | + // Wait for the server to close the connection. | |
| 160 | + f.channel().closeFuture().sync(); | |
| 161 | + } catch (Exception e) { | |
| 162 | + log.error("Error ->", e); | |
| 163 | + log.error("<- Error"); | |
| 164 | + } finally { | |
| 165 | + // Shut down executor threads to exit.Ahkk | |
| 166 | + try { | |
| 167 | + log.info("ShutdownGracefully the connection group"); | |
| 168 | + group.shutdownGracefully().sync(); | |
| 169 | + } catch (InterruptedException e) { | |
| 170 | + log.error("", e); | |
| 171 | + } | |
| 172 | + } | |
| 173 | + } | |
| 174 | +} | |
| 0 | 175 | \ No newline at end of file | ... | ... |
src/main/java/cn/org/hentai/jtt1078/server/Session.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/server/Session.java | |
| 1 | +package cn.org.hentai.jtt1078.server; | |
| 2 | + | |
| 3 | +import java.util.HashMap; | |
| 4 | +import java.util.Map; | |
| 5 | +import java.util.Set; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * Created by matrixy on 2019/4/10. | |
| 9 | + */ | |
| 10 | +public final class Session | |
| 11 | +{ | |
| 12 | + Map<String, Object> attributes; | |
| 13 | + public Session() | |
| 14 | + { | |
| 15 | + this.attributes = new HashMap<String, Object>(); | |
| 16 | + } | |
| 17 | + | |
| 18 | + public Session set(String key, Object value) | |
| 19 | + { | |
| 20 | + this.attributes.put(key, value); | |
| 21 | + return this; | |
| 22 | + } | |
| 23 | + | |
| 24 | + public boolean has(String key) | |
| 25 | + { | |
| 26 | + return this.attributes.containsKey(key); | |
| 27 | + } | |
| 28 | + | |
| 29 | + public Set<String> keys() | |
| 30 | + { | |
| 31 | + return this.attributes.keySet(); | |
| 32 | + } | |
| 33 | + | |
| 34 | + public <T> T get(String key) | |
| 35 | + { | |
| 36 | + return (T) this.attributes.get(key); | |
| 37 | + } | |
| 38 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/server/SessionManager.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/server/SessionManager.java | |
| 1 | +package cn.org.hentai.jtt1078.server; | |
| 2 | + | |
| 3 | +import io.netty.channel.Channel; | |
| 4 | +import org.apache.commons.collections.map.HashedMap; | |
| 5 | + | |
| 6 | +import java.util.Map; | |
| 7 | + | |
| 8 | +public final class SessionManager | |
| 9 | +{ | |
| 10 | + private static final Map<String, Object> mappings = new HashedMap(); | |
| 11 | + | |
| 12 | + public static void init() | |
| 13 | + { | |
| 14 | + // ... | |
| 15 | + } | |
| 16 | + | |
| 17 | + public static <T> T get(Channel channel, String key) | |
| 18 | + { | |
| 19 | + return (T) mappings.get(channel.id().asLongText() + key); | |
| 20 | + } | |
| 21 | + | |
| 22 | + public static void set(Channel channel, String key, Object value) | |
| 23 | + { | |
| 24 | + mappings.put(channel.id().asLongText() + key, value); | |
| 25 | + } | |
| 26 | + | |
| 27 | + public static boolean contains(Channel channel, String key) | |
| 28 | + { | |
| 29 | + return mappings.containsKey(channel.id().asLongText() + key); | |
| 30 | + } | |
| 31 | +} | |
| 0 | 32 | \ No newline at end of file | ... | ... |
src/main/java/cn/org/hentai/jtt1078/subscriber/RTMPPublisher.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/subscriber/RTMPPublisher.java | |
| 1 | +package cn.org.hentai.jtt1078.subscriber; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.MP3Encoder; | |
| 4 | +import cn.org.hentai.jtt1078.flv.AudioTag; | |
| 5 | +import cn.org.hentai.jtt1078.flv.FlvAudioTagEncoder; | |
| 6 | +import cn.org.hentai.jtt1078.flv.FlvEncoder; | |
| 7 | +import cn.org.hentai.jtt1078.util.*; | |
| 8 | +import io.netty.buffer.ByteBuf; | |
| 9 | +import io.netty.channel.ChannelHandlerContext; | |
| 10 | +import org.slf4j.Logger; | |
| 11 | +import org.slf4j.LoggerFactory; | |
| 12 | + | |
| 13 | +import java.io.InputStream; | |
| 14 | +import java.io.OutputStream; | |
| 15 | +import java.util.LinkedList; | |
| 16 | + | |
| 17 | +public class RTMPPublisher extends Thread | |
| 18 | +{ | |
| 19 | + static Logger logger = LoggerFactory.getLogger(RTMPPublisher.class); | |
| 20 | + | |
| 21 | + String tag = null; | |
| 22 | + Process process = null; | |
| 23 | + | |
| 24 | + public RTMPPublisher(String tag) | |
| 25 | + { | |
| 26 | + this.tag = tag; | |
| 27 | + } | |
| 28 | + | |
| 29 | + @Override | |
| 30 | + public void run() | |
| 31 | + { | |
| 32 | + InputStream stderr = null; | |
| 33 | + int len = -1; | |
| 34 | + byte[] buff = new byte[512]; | |
| 35 | + boolean debugMode = "on".equalsIgnoreCase(Configs.get("debug.mode")); | |
| 36 | + | |
| 37 | + try | |
| 38 | + { | |
| 39 | + String rtmpUrl = Configs.get("rtmp.url").replaceAll("\\{TAG\\}", tag); | |
| 40 | + String cmd = String.format("%s -i http://localhost:%d/video/%s -vcodec copy -acodec aac -f flv %s", | |
| 41 | + Configs.get("ffmpeg.path"), | |
| 42 | + Configs.getInt("server.http.port", 3333), | |
| 43 | + tag, | |
| 44 | + rtmpUrl | |
| 45 | + ); | |
| 46 | + logger.info("Execute: {}", cmd); | |
| 47 | + process = Runtime.getRuntime().exec(cmd); | |
| 48 | + stderr = process.getErrorStream(); | |
| 49 | + while ((len = stderr.read(buff)) > -1) | |
| 50 | + { | |
| 51 | + if (debugMode) System.out.print(new String(buff, 0, len)); | |
| 52 | + } | |
| 53 | + logger.info("Process FFMPEG exited..."); | |
| 54 | + } | |
| 55 | + catch(Exception ex) | |
| 56 | + { | |
| 57 | + logger.error("publish failed", ex); | |
| 58 | + } | |
| 59 | + } | |
| 60 | + | |
| 61 | + public void close() | |
| 62 | + { | |
| 63 | + try { if (process != null) process.destroyForcibly(); } catch(Exception e) { } | |
| 64 | + } | |
| 65 | +} | |
| 0 | 66 | \ No newline at end of file | ... | ... |
src/main/java/cn/org/hentai/jtt1078/subscriber/Subscriber.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/subscriber/Subscriber.java | |
| 1 | +package cn.org.hentai.jtt1078.subscriber; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.flv.FlvEncoder; | |
| 4 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 5 | +import io.netty.channel.ChannelFuture; | |
| 6 | +import io.netty.channel.ChannelHandlerContext; | |
| 7 | +import org.slf4j.Logger; | |
| 8 | +import org.slf4j.LoggerFactory; | |
| 9 | + | |
| 10 | +import java.util.LinkedList; | |
| 11 | +import java.util.concurrent.atomic.AtomicLong; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * Created by matrixy on 2020/1/11. | |
| 15 | + */ | |
| 16 | +public abstract class Subscriber extends Thread | |
| 17 | +{ | |
| 18 | + static Logger logger = LoggerFactory.getLogger(Subscriber.class); | |
| 19 | + static final AtomicLong SEQUENCE = new AtomicLong(0L); | |
| 20 | + | |
| 21 | + private long id; | |
| 22 | + private String tag; | |
| 23 | + private Object lock; | |
| 24 | + private ChannelHandlerContext context; | |
| 25 | + protected LinkedList<byte[]> messages; | |
| 26 | + | |
| 27 | + public Subscriber(String tag, ChannelHandlerContext ctx) | |
| 28 | + { | |
| 29 | + this.tag = tag; | |
| 30 | + this.context = ctx; | |
| 31 | + this.lock = new Object(); | |
| 32 | + this.messages = new LinkedList<byte[]>(); | |
| 33 | + | |
| 34 | + this.id = SEQUENCE.getAndAdd(1L); | |
| 35 | + } | |
| 36 | + | |
| 37 | + public long getId() | |
| 38 | + { | |
| 39 | + return this.id; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public String getTag() | |
| 43 | + { | |
| 44 | + return this.tag; | |
| 45 | + } | |
| 46 | + | |
| 47 | + public abstract void onVideoData(long timeoffset, byte[] data, FlvEncoder flvEncoder); | |
| 48 | + | |
| 49 | + public abstract void onAudioData(long timeoffset, byte[] data, FlvEncoder flvEncoder); | |
| 50 | + | |
| 51 | + public void enqueue(byte[] data) | |
| 52 | + { | |
| 53 | + if (data == null) return; | |
| 54 | + synchronized (lock) | |
| 55 | + { | |
| 56 | + messages.addLast(data); | |
| 57 | + lock.notify(); | |
| 58 | + } | |
| 59 | + } | |
| 60 | + | |
| 61 | + public void run() | |
| 62 | + { | |
| 63 | + loop : while (!this.isInterrupted()) | |
| 64 | + { | |
| 65 | + try | |
| 66 | + { | |
| 67 | + byte[] data = take(); | |
| 68 | + if (data != null) send(data).await(); | |
| 69 | + } | |
| 70 | + catch(Exception ex) | |
| 71 | + { | |
| 72 | + //销毁线程时,如果有锁wait就不会销毁线程,抛出InterruptedException异常 | |
| 73 | + if (ex instanceof InterruptedException) | |
| 74 | + { | |
| 75 | + break loop; | |
| 76 | + } | |
| 77 | + logger.error("send failed", ex); | |
| 78 | + } | |
| 79 | + } | |
| 80 | + logger.info("subscriber closed"); | |
| 81 | + } | |
| 82 | + | |
| 83 | + protected byte[] take() | |
| 84 | + { | |
| 85 | + byte[] data = null; | |
| 86 | + try | |
| 87 | + { | |
| 88 | + synchronized (lock) | |
| 89 | + { | |
| 90 | + while (messages.isEmpty()) | |
| 91 | + { | |
| 92 | + lock.wait(100); | |
| 93 | + if (this.isInterrupted()) return null; | |
| 94 | + } | |
| 95 | + data = messages.removeFirst(); | |
| 96 | + } | |
| 97 | + return data; | |
| 98 | + } | |
| 99 | + catch(Exception ex) | |
| 100 | + { | |
| 101 | + this.interrupt(); | |
| 102 | + return null; | |
| 103 | + } | |
| 104 | + } | |
| 105 | + | |
| 106 | + public void close() | |
| 107 | + { | |
| 108 | + this.interrupt(); | |
| 109 | + } | |
| 110 | + | |
| 111 | + public ChannelFuture send(byte[] message) | |
| 112 | + { | |
| 113 | + return context.writeAndFlush(message); | |
| 114 | + } | |
| 115 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/subscriber/VideoSubscriber.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/subscriber/VideoSubscriber.java | |
| 1 | +package cn.org.hentai.jtt1078.subscriber; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.MP3Encoder; | |
| 4 | +import cn.org.hentai.jtt1078.flv.AudioTag; | |
| 5 | +import cn.org.hentai.jtt1078.flv.FlvAudioTagEncoder; | |
| 6 | +import cn.org.hentai.jtt1078.flv.FlvEncoder; | |
| 7 | +import cn.org.hentai.jtt1078.util.ByteBufUtils; | |
| 8 | +import cn.org.hentai.jtt1078.util.FLVUtils; | |
| 9 | +import cn.org.hentai.jtt1078.util.HttpChunk; | |
| 10 | +import io.netty.buffer.ByteBuf; | |
| 11 | +import io.netty.channel.ChannelHandlerContext; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * Created by matrixy on 2020/1/13. | |
| 15 | + */ | |
| 16 | +public class VideoSubscriber extends Subscriber | |
| 17 | +{ | |
| 18 | + private long videoTimestamp = 0; | |
| 19 | + private long audioTimestamp = 0; | |
| 20 | + private long lastVideoFrameTimeOffset = 0; | |
| 21 | + private long lastAudioFrameTimeOffset = 0; | |
| 22 | + private boolean videoHeaderSent = false; | |
| 23 | + | |
| 24 | + public VideoSubscriber(String tag, ChannelHandlerContext ctx) | |
| 25 | + { | |
| 26 | + super(tag, ctx); | |
| 27 | + } | |
| 28 | + | |
| 29 | + @Override | |
| 30 | + public void onVideoData(long timeoffset, byte[] data, FlvEncoder flvEncoder) | |
| 31 | + { | |
| 32 | + if (lastVideoFrameTimeOffset == 0) lastVideoFrameTimeOffset = timeoffset; | |
| 33 | + | |
| 34 | + // 之前是不是已经发送过了?没有的话,需要补发FLV HEADER的。。。 | |
| 35 | + if (videoHeaderSent == false && flvEncoder.videoReady()) | |
| 36 | + { | |
| 37 | + enqueue(HttpChunk.make(flvEncoder.getHeader().getBytes())); | |
| 38 | + enqueue(HttpChunk.make(flvEncoder.getVideoHeader().getBytes())); | |
| 39 | + | |
| 40 | + // 直接下发第一个I帧 | |
| 41 | + byte[] iFrame = flvEncoder.getLastIFrame(); | |
| 42 | + if (iFrame != null) | |
| 43 | + { | |
| 44 | + FLVUtils.resetTimestamp(iFrame, (int) videoTimestamp); | |
| 45 | + enqueue(HttpChunk.make(iFrame)); | |
| 46 | + } | |
| 47 | + | |
| 48 | + videoHeaderSent = true; | |
| 49 | + } | |
| 50 | + | |
| 51 | + if (data == null) return; | |
| 52 | + | |
| 53 | + // 修改时间戳 | |
| 54 | + // System.out.println("Time: " + videoTimestamp + ", current: " + timeoffset); | |
| 55 | + FLVUtils.resetTimestamp(data, (int) videoTimestamp); | |
| 56 | + videoTimestamp += (int)(timeoffset - lastVideoFrameTimeOffset); | |
| 57 | + lastVideoFrameTimeOffset = timeoffset; | |
| 58 | + | |
| 59 | + enqueue(HttpChunk.make(data)); | |
| 60 | + } | |
| 61 | + | |
| 62 | + private FlvAudioTagEncoder audioEncoder = new FlvAudioTagEncoder(); | |
| 63 | + MP3Encoder mp3Encoder = new MP3Encoder(); | |
| 64 | + | |
| 65 | + @Override | |
| 66 | + public void onAudioData(long timeoffset, byte[] data, FlvEncoder flvEncoder) | |
| 67 | + { | |
| 68 | + if (!videoHeaderSent) return; | |
| 69 | + | |
| 70 | + byte[] mp3Data = mp3Encoder.encode(data); | |
| 71 | + if (mp3Data == null || mp3Data.length == 0) return; | |
| 72 | + AudioTag audioTag = new AudioTag(0, mp3Data.length + 1, AudioTag.MP3, (byte) 0, (byte)1, (byte) 0, mp3Data); | |
| 73 | + byte[] frameData = null; | |
| 74 | + try | |
| 75 | + { | |
| 76 | + ByteBuf audioBuf = audioEncoder.encode(audioTag); | |
| 77 | + frameData = ByteBufUtils.readReadableBytes(audioBuf); | |
| 78 | + } | |
| 79 | + catch (Exception e) | |
| 80 | + { | |
| 81 | + e.printStackTrace(); | |
| 82 | + } | |
| 83 | + | |
| 84 | + if (lastAudioFrameTimeOffset == 0) lastAudioFrameTimeOffset = timeoffset; | |
| 85 | + | |
| 86 | + if (data == null) return; | |
| 87 | + | |
| 88 | + FLVUtils.resetTimestamp(frameData, (int) audioTimestamp); | |
| 89 | + audioTimestamp += (int)(timeoffset - lastAudioFrameTimeOffset); | |
| 90 | + lastAudioFrameTimeOffset = timeoffset; | |
| 91 | + | |
| 92 | + enqueue(HttpChunk.make(frameData)); | |
| 93 | + } | |
| 94 | + | |
| 95 | + @Override | |
| 96 | + public void close() | |
| 97 | + { | |
| 98 | + super.close(); | |
| 99 | + mp3Encoder.close(); | |
| 100 | + } | |
| 101 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/AudioTest.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/AudioTest.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.G711Codec; | |
| 4 | +import cn.org.hentai.jtt1078.server.Jtt1078Decoder; | |
| 5 | +import cn.org.hentai.jtt1078.util.ByteUtils; | |
| 6 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 7 | + | |
| 8 | +import java.io.FileInputStream; | |
| 9 | +import java.io.FileOutputStream; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * Created by matrixy on 2019/12/21. | |
| 13 | + */ | |
| 14 | +public class AudioTest | |
| 15 | +{ | |
| 16 | + public static void main(String[] args) throws Exception | |
| 17 | + { | |
| 18 | + int len = -1; | |
| 19 | + byte[] block = new byte[1024]; | |
| 20 | + FileInputStream fis = new FileInputStream("e:\\test\\streaming.hex"); | |
| 21 | + Jtt1078Decoder decoder = new Jtt1078Decoder(); | |
| 22 | + G711Codec codec = new G711Codec(); | |
| 23 | + FileOutputStream fos = new FileOutputStream("e:\\test\\fuckfuckfuck1111.pcm"); | |
| 24 | + while ((len = fis.read(block)) > -1) | |
| 25 | + { | |
| 26 | + decoder.write(block, 0, len); | |
| 27 | + while (true) | |
| 28 | + { | |
| 29 | + Packet p = decoder.decode(); | |
| 30 | + if (p == null) break; | |
| 31 | + | |
| 32 | + int lengthOffset = 28; | |
| 33 | + int dataType = (p.seek(15).nextByte() >> 4) & 0x0f; | |
| 34 | + // 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段 | |
| 35 | + if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; | |
| 36 | + else if (dataType == 0x03) lengthOffset = 28 - 4; | |
| 37 | + | |
| 38 | + if (dataType == 0x03) | |
| 39 | + { | |
| 40 | + byte[] pcmData = codec.toPCM(p.seek(lengthOffset + 2).nextBytes()); | |
| 41 | + fos.write(pcmData); | |
| 42 | + fos.flush(); | |
| 43 | + } | |
| 44 | + } | |
| 45 | + } | |
| 46 | + fos.close(); | |
| 47 | + fis.close(); | |
| 48 | + } | |
| 49 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/ChannelTest.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/ChannelTest.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.util.ByteHolder; | |
| 4 | +import cn.org.hentai.jtt1078.util.ByteUtils; | |
| 5 | + | |
| 6 | +import java.io.ByteArrayOutputStream; | |
| 7 | +import java.io.IOException; | |
| 8 | +import java.nio.ByteBuffer; | |
| 9 | +import java.nio.channels.ByteChannel; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * Created by matrixy on 2020/1/9. | |
| 13 | + */ | |
| 14 | +public class ChannelTest implements ByteChannel | |
| 15 | +{ | |
| 16 | + byte[] temp = new byte[4]; | |
| 17 | + ByteHolder buffer = new ByteHolder(1024); | |
| 18 | + | |
| 19 | + // 读出,存入dst | |
| 20 | + @Override | |
| 21 | + public int read(ByteBuffer dst) throws IOException | |
| 22 | + { | |
| 23 | + dst.flip(); | |
| 24 | + int len = Math.min(4, buffer.size()); | |
| 25 | + if (dst.remaining() > len) | |
| 26 | + { | |
| 27 | + buffer.sliceInto(temp, len); | |
| 28 | + dst.put(temp, 0, len); | |
| 29 | + } | |
| 30 | + else | |
| 31 | + { | |
| 32 | + // 丢掉??? | |
| 33 | + } | |
| 34 | + dst.flip(); | |
| 35 | + return len; | |
| 36 | + } | |
| 37 | + | |
| 38 | + // 从src读出,写入进来 | |
| 39 | + @Override | |
| 40 | + public int write(ByteBuffer src) throws IOException | |
| 41 | + { | |
| 42 | + int len = -1; | |
| 43 | + // src.flip(); | |
| 44 | + len = Math.min(4, src.limit()); | |
| 45 | + src.get(temp, 0, len); | |
| 46 | + buffer.write(temp, 0, len); | |
| 47 | + // src.flip(); | |
| 48 | + System.out.println("write: " + len); | |
| 49 | + return len; | |
| 50 | + } | |
| 51 | + | |
| 52 | + @Override | |
| 53 | + public boolean isOpen() | |
| 54 | + { | |
| 55 | + return true; | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Override | |
| 59 | + public void close() throws IOException | |
| 60 | + { | |
| 61 | + | |
| 62 | + } | |
| 63 | + | |
| 64 | + public byte[] array() | |
| 65 | + { | |
| 66 | + return buffer.array(); | |
| 67 | + } | |
| 68 | + | |
| 69 | + public static void main(String[] args) throws Exception | |
| 70 | + { | |
| 71 | + ChannelTest chl = new ChannelTest(); | |
| 72 | + ByteBuffer buffer = ByteBuffer.allocate(4); | |
| 73 | + java.nio.ByteBuffer xx; | |
| 74 | + System.out.println(buffer.getClass().getName()); | |
| 75 | + for (int i = 0; i < 4096; i++) | |
| 76 | + buffer.put((byte)'f'); | |
| 77 | + /* | |
| 78 | + buffer.putLong(0x1122334455667788L); | |
| 79 | + buffer.flip(); | |
| 80 | + // flip太迷惑了 | |
| 81 | + buffer.isReadOnly(); | |
| 82 | + int len = chl.write(buffer); | |
| 83 | + len = chl.write(buffer); | |
| 84 | + ByteUtils.dump(chl.array()); | |
| 85 | + */ | |
| 86 | + } | |
| 87 | + | |
| 88 | + static final class ByteBufferWrapper | |
| 89 | + { | |
| 90 | + boolean writeMode; | |
| 91 | + ByteBuffer buffer; | |
| 92 | + | |
| 93 | + private ByteBufferWrapper(int size) | |
| 94 | + { | |
| 95 | + this.buffer = ByteBuffer.allocate(size); | |
| 96 | + } | |
| 97 | + | |
| 98 | + // 控制写入,代理过来 | |
| 99 | + public void write() | |
| 100 | + { | |
| 101 | + | |
| 102 | + } | |
| 103 | + | |
| 104 | + // 写出就无所谓了 | |
| 105 | + | |
| 106 | + public static ByteBufferWrapper create(int size) | |
| 107 | + { | |
| 108 | + return new ByteBufferWrapper(size); | |
| 109 | + } | |
| 110 | + } | |
| 111 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/FuckTest.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/FuckTest.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.util.ByteUtils; | |
| 4 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 5 | + | |
| 6 | +import java.io.DataInputStream; | |
| 7 | +import java.io.FileInputStream; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by matrixy on 2020/3/19. | |
| 11 | + */ | |
| 12 | +public class FuckTest | |
| 13 | +{ | |
| 14 | + public static void main(String[] args) throws Exception | |
| 15 | + { | |
| 16 | + String line; | |
| 17 | + DataInputStream dis = new DataInputStream(new FileInputStream("d:\\temp\\rtp.txt")); | |
| 18 | + while ((line = dis.readLine()) != null) | |
| 19 | + { | |
| 20 | + byte[] rtp = ByteUtils.parse(line); | |
| 21 | + Packet packet = Packet.create(rtp); | |
| 22 | + | |
| 23 | + int lengthOffset = 28; | |
| 24 | + int dataType = (packet.seek(15).nextByte() >> 4) & 0x0f; | |
| 25 | + int pkType = packet.seek(15).nextByte() & 0x0f; | |
| 26 | + // 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段 | |
| 27 | + if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; | |
| 28 | + else if (dataType == 0x03) lengthOffset = 28 - 4; | |
| 29 | + | |
| 30 | + if (dataType <= 0x02) | |
| 31 | + { | |
| 32 | + if (dataType == 0x00) System.out.println("I Frame---------------------------------"); | |
| 33 | + if (dataType == 0x01) System.out.println("P Frame"); | |
| 34 | + if (dataType == 0x02) System.out.println("B Frame"); | |
| 35 | + } | |
| 36 | + } | |
| 37 | + } | |
| 38 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/G711ATest.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/G711ATest.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.codec.G711Codec; | |
| 4 | + | |
| 5 | +import java.io.FileInputStream; | |
| 6 | +import java.io.FileOutputStream; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * Created by matrixy on 2019/12/21. | |
| 10 | + */ | |
| 11 | +public class G711ATest | |
| 12 | +{ | |
| 13 | + public static void main(String[] args) throws Exception | |
| 14 | + { | |
| 15 | + int len = -1; | |
| 16 | + byte[] block = new byte[1024]; | |
| 17 | + FileInputStream fis = new FileInputStream("E:\\workspace\\enc_dec_audio\\g711\\encode_out.g711a"); | |
| 18 | + FileOutputStream fos = new FileOutputStream("E:\\test\\fuckfuckfuck111.pcm"); | |
| 19 | + G711Codec codec = new G711Codec(); | |
| 20 | + while ((len = fis.read(block)) > -1) | |
| 21 | + { | |
| 22 | + byte[] pcmData = null; | |
| 23 | + if (len == 1024) | |
| 24 | + { | |
| 25 | + pcmData = codec.toPCM(block); | |
| 26 | + } | |
| 27 | + else | |
| 28 | + { | |
| 29 | + byte[] temp = new byte[len]; | |
| 30 | + System.arraycopy(block, 0, temp, 0, len); | |
| 31 | + pcmData = codec.toPCM(temp); | |
| 32 | + } | |
| 33 | + fos.write(pcmData); | |
| 34 | + fos.flush(); | |
| 35 | + } | |
| 36 | + fis.close(); | |
| 37 | + fos.close(); | |
| 38 | + } | |
| 39 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/MP3Test.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/MP3Test.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import de.sciss.jump3r.lowlevel.LameEncoder; | |
| 4 | +import de.sciss.jump3r.mp3.Lame; | |
| 5 | + | |
| 6 | +import javax.sound.sampled.AudioFormat; | |
| 7 | +import java.io.ByteArrayOutputStream; | |
| 8 | +import java.io.FileInputStream; | |
| 9 | +import java.io.FileOutputStream; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * Created by matrixy on 2020/4/27. | |
| 13 | + */ | |
| 14 | +public class MP3Test | |
| 15 | +{ | |
| 16 | + public static void main(String[] args) throws Exception | |
| 17 | + { | |
| 18 | + AudioFormat sourceFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000, 16, 1, 1 * 2, -1, false); | |
| 19 | + LameEncoder encoder = new LameEncoder(sourceFormat, 256, 3, Lame.MEDIUM, false); | |
| 20 | + | |
| 21 | + byte[] block = new byte[320]; | |
| 22 | + int len = -1; | |
| 23 | + FileInputStream fis = new FileInputStream("d:\\temp\\hello.pcm"); | |
| 24 | + ByteArrayOutputStream mp3 = new ByteArrayOutputStream(encoder.getOutputBufferSize()); | |
| 25 | + byte[] buffer = new byte[encoder.getPCMBufferSize()]; | |
| 26 | + int bytesToTransfer = 0; | |
| 27 | + int bytesWritten; | |
| 28 | + int currentPcmPosition = 0; | |
| 29 | + | |
| 30 | + FileOutputStream fos = new FileOutputStream("d:\\temp\\fuck.mp3"); | |
| 31 | + | |
| 32 | + while ((len = fis.read(block)) > -1) | |
| 33 | + { | |
| 34 | + bytesToTransfer = len; | |
| 35 | + currentPcmPosition = 0; | |
| 36 | + while (0 < (bytesWritten = encoder.encodeBuffer(block, currentPcmPosition, bytesToTransfer, buffer))) | |
| 37 | + { | |
| 38 | + currentPcmPosition += bytesToTransfer; | |
| 39 | + bytesToTransfer = Math.min(buffer.length, len - currentPcmPosition); | |
| 40 | + | |
| 41 | + mp3.write(buffer, 0, bytesWritten); | |
| 42 | + fos.write(buffer, 0, bytesWritten); | |
| 43 | + | |
| 44 | + System.out.println(String.format("pcm data: %4d, written: %4d, pos: %4d", len, bytesWritten, currentPcmPosition)); | |
| 45 | + } | |
| 46 | + System.out.println(); | |
| 47 | + } | |
| 48 | + | |
| 49 | + fos.close(); | |
| 50 | + fis.close(); | |
| 51 | + | |
| 52 | + encoder.close(); | |
| 53 | + } | |
| 54 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/RTPGenerate.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/RTPGenerate.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.flv.FlvEncoder; | |
| 4 | +import cn.org.hentai.jtt1078.server.Jtt1078Decoder; | |
| 5 | +import cn.org.hentai.jtt1078.util.ByteHolder; | |
| 6 | +import cn.org.hentai.jtt1078.util.ByteUtils; | |
| 7 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 8 | + | |
| 9 | +import java.io.FileInputStream; | |
| 10 | +import java.io.FileOutputStream; | |
| 11 | +import java.io.InputStream; | |
| 12 | +import java.io.OutputStream; | |
| 13 | +import java.util.LinkedList; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * Created by matrixy on 2019/12/16. | |
| 17 | + */ | |
| 18 | +public class RTPGenerate | |
| 19 | +{ | |
| 20 | + public static void main(String[] args) throws Exception | |
| 21 | + { | |
| 22 | + InputStream input = new FileInputStream("d:\\test\\1078\\streamax-20191209.bin"); | |
| 23 | + LinkedList<Packet> packets = readPackets(input); | |
| 24 | + | |
| 25 | + for (int i = 0; i < 100; i++) | |
| 26 | + { | |
| 27 | + String sim = String.format("013800138%03d", i); | |
| 28 | + int channel = 1; | |
| 29 | + | |
| 30 | + try (OutputStream output = new FileOutputStream("d:\\test\\1078\\temp\\" + sim + "-" + channel + ".bin")) | |
| 31 | + { | |
| 32 | + for (Packet p : packets) | |
| 33 | + { | |
| 34 | + p.seek(8).putBytes(toBCD(sim)); | |
| 35 | + p.seek(14).putByte((byte)channel); | |
| 36 | + output.write(p.getBytes()); | |
| 37 | + } | |
| 38 | + System.out.println(String.format(" -> %s-%d generated...", sim, channel)); | |
| 39 | + } | |
| 40 | + catch(Exception ex) | |
| 41 | + { | |
| 42 | + ex.printStackTrace(); | |
| 43 | + System.out.println(ex); | |
| 44 | + } | |
| 45 | + } | |
| 46 | + | |
| 47 | + input.close(); | |
| 48 | + } | |
| 49 | + | |
| 50 | + public static LinkedList<Packet> readPackets(InputStream input) throws Exception | |
| 51 | + { | |
| 52 | + int len = -1; | |
| 53 | + byte[] block = new byte[1024]; | |
| 54 | + Jtt1078Decoder decoder = new Jtt1078Decoder(); | |
| 55 | + | |
| 56 | + LinkedList<Packet> packets = new LinkedList(); | |
| 57 | + | |
| 58 | + while ((len = input.read(block)) > -1) | |
| 59 | + { | |
| 60 | + decoder.write(block, 0, len); | |
| 61 | + while (true) | |
| 62 | + { | |
| 63 | + Packet p = decoder.decode(); | |
| 64 | + if (p == null) break; | |
| 65 | + | |
| 66 | + packets.add(p); | |
| 67 | + } | |
| 68 | + } | |
| 69 | + | |
| 70 | + return packets; | |
| 71 | + } | |
| 72 | + | |
| 73 | + public static byte[] toBCD(String sim) | |
| 74 | + { | |
| 75 | + byte[] bcd = new byte[sim.length() / 2]; | |
| 76 | + for (int i = 0, k = 0, l = sim.length(); i < l; i+=2) | |
| 77 | + { | |
| 78 | + char a = (char)(sim.charAt(i) - '0'); | |
| 79 | + char b = (char)(sim.charAt(i + 1) - '0'); | |
| 80 | + bcd[k++] = ((byte)(a << 4 | b)); | |
| 81 | + } | |
| 82 | + return bcd; | |
| 83 | + } | |
| 84 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/UnPack.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/UnPack.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.server.Jtt1078Decoder; | |
| 4 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 5 | + | |
| 6 | +import java.io.FileInputStream; | |
| 7 | +import java.io.FileOutputStream; | |
| 8 | + | |
| 9 | +public class UnPack | |
| 10 | +{ | |
| 11 | + public static void main(String[] args) throws Exception | |
| 12 | + { | |
| 13 | + FileInputStream input = new FileInputStream("d:\\test\\1078\\d.bin"); | |
| 14 | + FileOutputStream output = new FileOutputStream("d:\\test\\1078\\fuck.1078.xxx"); | |
| 15 | + | |
| 16 | + int len = -1; | |
| 17 | + byte[] block = new byte[1024]; | |
| 18 | + Jtt1078Decoder decoder = new Jtt1078Decoder(); | |
| 19 | + while (true) | |
| 20 | + { | |
| 21 | + len = input.read(block); | |
| 22 | + if (len == -1) break; | |
| 23 | + decoder.write(block, 0, len); | |
| 24 | + | |
| 25 | + while (true) | |
| 26 | + { | |
| 27 | + Packet p = decoder.decode(); | |
| 28 | + if (p == null) break; | |
| 29 | + | |
| 30 | + int lengthOffset = 28; | |
| 31 | + int dataType = (p.seek(15).nextByte() >> 4) & 0x0f; | |
| 32 | + // 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段 | |
| 33 | + if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; | |
| 34 | + else if (dataType == 0x03) lengthOffset = 28 - 4; | |
| 35 | + | |
| 36 | + // FFMpegManager.getInstance().feed(publisherId, packet.seek(lengthOffset + 2).nextBytes()); | |
| 37 | + if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) | |
| 38 | + { | |
| 39 | + // 视频 | |
| 40 | + // p.seek(lengthOffset + 2).nextBytes() | |
| 41 | + // output.write(p.seek(lengthOffset + 2).nextBytes()); | |
| 42 | + System.out.println(p.seek(lengthOffset).nextShort()); | |
| 43 | + } | |
| 44 | + else | |
| 45 | + { | |
| 46 | + // 音频 | |
| 47 | + // p.seek(lengthOffset + 2).nextBytes() | |
| 48 | + } | |
| 49 | + } | |
| 50 | + } | |
| 51 | + output.flush(); | |
| 52 | + output.close(); | |
| 53 | + input.close(); | |
| 54 | + } | |
| 55 | +} | |
| 0 | 56 | \ No newline at end of file | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/VideoPushTest.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/VideoPushTest.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import java.io.FileInputStream; | |
| 4 | +import java.io.InputStream; | |
| 5 | +import java.io.OutputStream; | |
| 6 | +import java.net.Socket; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * Created by matrixy on 2019/4/10. | |
| 10 | + */ | |
| 11 | +public class VideoPushTest | |
| 12 | +{ | |
| 13 | + public static void main(String[] args) throws Exception | |
| 14 | + { | |
| 15 | + Socket conn = new Socket("localhost", 1078); | |
| 16 | + OutputStream os = conn.getOutputStream(); | |
| 17 | + | |
| 18 | + // InputStream fis = new FileInputStream("e:\\workspace\\enc_dec_audio\\streamax.bin"); | |
| 19 | + // InputStream fis = new FileInputStream("e:\\test\\streaming.hex"); | |
| 20 | + InputStream fis = VideoPushTest.class.getResourceAsStream("/tcpdump.bin"); | |
| 21 | + int len = -1; | |
| 22 | + byte[] block = new byte[512]; | |
| 23 | + while ((len = fis.read(block)) > -1) | |
| 24 | + { | |
| 25 | + os.write(block, 0, len); | |
| 26 | + os.flush(); | |
| 27 | + Thread.sleep(20); | |
| 28 | + System.out.println("sending..."); | |
| 29 | + } | |
| 30 | + os.close(); | |
| 31 | + fis.close(); | |
| 32 | + conn.close(); | |
| 33 | + } | |
| 34 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/VideoServer.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/VideoServer.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.server.Jtt1078Decoder; | |
| 4 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 5 | + | |
| 6 | +import java.io.FileOutputStream; | |
| 7 | +import java.io.InputStream; | |
| 8 | +import java.net.ServerSocket; | |
| 9 | +import java.net.Socket; | |
| 10 | +import java.util.LinkedList; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * Created by houcheng on 2019-12-10. | |
| 14 | + */ | |
| 15 | +public class VideoServer | |
| 16 | +{ | |
| 17 | + public static void main(String[] args) throws Exception | |
| 18 | + { | |
| 19 | + System.out.println("started..."); | |
| 20 | + | |
| 21 | + String command = ("ffmpeg -f h264 -i /opt/test/xxoo.Video -f sln -ar 8000 -ac 1 -i /opt/test/xxoo.Audio -vcodec copy -acodec aac -map 0:v:0 -map 1:a:0 -probesize 512 -analyzeduration 100 -f flv rtmp://localhost/live/fuck"); | |
| 22 | + Process process = Runtime.getRuntime().exec(command); | |
| 23 | + new Reader(process.getErrorStream()).start(); | |
| 24 | + | |
| 25 | + Thread.sleep(2000); | |
| 26 | + | |
| 27 | + ServerSocket server = new ServerSocket(1078, 100); | |
| 28 | + Socket conn = server.accept(); | |
| 29 | + System.out.println("Connected from: " + conn.getRemoteSocketAddress()); | |
| 30 | + InputStream input = conn.getInputStream(); | |
| 31 | + | |
| 32 | + Publisher videoPublisher = new VideoPublisher(); | |
| 33 | + Publisher audioPublisher = new AudioPublisher(); | |
| 34 | + | |
| 35 | + videoPublisher.start(); | |
| 36 | + audioPublisher.start(); | |
| 37 | + | |
| 38 | + int len = -1; | |
| 39 | + byte[] block = new byte[1024]; | |
| 40 | + Jtt1078Decoder decoder = new Jtt1078Decoder(); | |
| 41 | + while (true) | |
| 42 | + { | |
| 43 | + len = input.read(block); | |
| 44 | + if (len == -1) break; | |
| 45 | + decoder.write(block, 0, len); | |
| 46 | + | |
| 47 | + while (true) | |
| 48 | + { | |
| 49 | + Packet p = decoder.decode(); | |
| 50 | + if (p == null) break; | |
| 51 | + | |
| 52 | + int lengthOffset = 28; | |
| 53 | + int dataType = (p.seek(15).nextByte() >> 4) & 0x0f; | |
| 54 | + // 透传数据类型:0100,没有后面的时间以及Last I Frame Interval和Last Frame Interval字段 | |
| 55 | + if (dataType == 0x04) lengthOffset = 28 - 8 - 2 - 2; | |
| 56 | + else if (dataType == 0x03) lengthOffset = 28 - 4; | |
| 57 | + | |
| 58 | + // FFMpegManager.getInstance().feed(publisherId, packet.seek(lengthOffset + 2).nextBytes()); | |
| 59 | + if (dataType == 0x00 || dataType == 0x01 || dataType == 0x02) | |
| 60 | + { | |
| 61 | + videoPublisher.publish(p.seek(lengthOffset + 2).nextBytes()); | |
| 62 | + } | |
| 63 | + else | |
| 64 | + { | |
| 65 | + audioPublisher.publish(p.seek(lengthOffset + 2).nextBytes()); | |
| 66 | + } | |
| 67 | + } | |
| 68 | + } | |
| 69 | + | |
| 70 | + System.in.read(); | |
| 71 | + } | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + static class Reader extends Thread | |
| 76 | + { | |
| 77 | + InputStream stdout = null; | |
| 78 | + public Reader(InputStream is) | |
| 79 | + { | |
| 80 | + this.stdout = is; | |
| 81 | + } | |
| 82 | + | |
| 83 | + public void run() | |
| 84 | + { | |
| 85 | + int len = -1; | |
| 86 | + byte[] block = new byte[512]; | |
| 87 | + try | |
| 88 | + { | |
| 89 | + while ((len = stdout.read(block)) > -1) | |
| 90 | + { | |
| 91 | + System.out.print(new String(block, 0, len)); | |
| 92 | + } | |
| 93 | + } | |
| 94 | + catch(Exception ex) | |
| 95 | + { | |
| 96 | + ex.printStackTrace(); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + } | |
| 100 | + | |
| 101 | + static class Publisher extends Thread | |
| 102 | + { | |
| 103 | + Object lock = new Object(); | |
| 104 | + LinkedList<byte[]> messages = new LinkedList(); | |
| 105 | + | |
| 106 | + public void publish(byte[] msg) | |
| 107 | + { | |
| 108 | + synchronized (lock) | |
| 109 | + { | |
| 110 | + messages.add(msg); | |
| 111 | + lock.notify(); | |
| 112 | + } | |
| 113 | + } | |
| 114 | + | |
| 115 | + public byte[] peek() | |
| 116 | + { | |
| 117 | + byte[] msg = null; | |
| 118 | + synchronized (lock) | |
| 119 | + { | |
| 120 | + while (messages.size() == 0) try { lock.wait(); } catch(Exception e) { } | |
| 121 | + msg = messages.removeFirst(); | |
| 122 | + } | |
| 123 | + return msg; | |
| 124 | + } | |
| 125 | + | |
| 126 | + public FileOutputStream open(String fname) | |
| 127 | + { | |
| 128 | + try | |
| 129 | + { | |
| 130 | + return new FileOutputStream(fname); | |
| 131 | + } | |
| 132 | + catch(Exception ex) | |
| 133 | + { | |
| 134 | + throw new RuntimeException(ex); | |
| 135 | + } | |
| 136 | + } | |
| 137 | + } | |
| 138 | + | |
| 139 | + static class VideoPublisher extends Publisher | |
| 140 | + { | |
| 141 | + public void run() | |
| 142 | + { | |
| 143 | + FileOutputStream fos = open("/opt/test/xxoo.Video"); | |
| 144 | + while (!this.isInterrupted()) | |
| 145 | + { | |
| 146 | + try | |
| 147 | + { | |
| 148 | + byte[] msg = peek(); | |
| 149 | + fos.write(msg); | |
| 150 | + fos.flush(); | |
| 151 | + } | |
| 152 | + catch(Exception ex) | |
| 153 | + { | |
| 154 | + ex.printStackTrace(); | |
| 155 | + break; | |
| 156 | + } | |
| 157 | + } | |
| 158 | + } | |
| 159 | + } | |
| 160 | + | |
| 161 | + static class AudioPublisher extends Publisher | |
| 162 | + { | |
| 163 | + public void run() | |
| 164 | + { | |
| 165 | + FileOutputStream fos = open("/opt/test/xxoo.Audio"); | |
| 166 | + while (!this.isInterrupted()) | |
| 167 | + { | |
| 168 | + try | |
| 169 | + { | |
| 170 | + byte[] msg = peek(); | |
| 171 | + fos.write(msg); | |
| 172 | + fos.flush(); | |
| 173 | + } | |
| 174 | + catch(Exception ex) | |
| 175 | + { | |
| 176 | + ex.printStackTrace(); | |
| 177 | + break; | |
| 178 | + } | |
| 179 | + } | |
| 180 | + } | |
| 181 | + } | |
| 182 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/test/WAVTest.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/test/WAVTest.java | |
| 1 | +package cn.org.hentai.jtt1078.test; | |
| 2 | + | |
| 3 | +import cn.org.hentai.jtt1078.util.ByteUtils; | |
| 4 | +import cn.org.hentai.jtt1078.util.Packet; | |
| 5 | + | |
| 6 | +import java.io.FileInputStream; | |
| 7 | +import java.io.FileOutputStream; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by matrixy on 2019/12/18. | |
| 11 | + */ | |
| 12 | +public class WAVTest | |
| 13 | +{ | |
| 14 | + public static void main(String[] args) throws Exception | |
| 15 | + { | |
| 16 | + int len; | |
| 17 | + byte[] block = new byte[1024 * 2048]; | |
| 18 | + FileInputStream fis = new FileInputStream("d:\\temp\\xxoo.pcm"); | |
| 19 | + Packet p = Packet.create(1024 * 2048); | |
| 20 | + while ((len = fis.read(block)) > -1) | |
| 21 | + { | |
| 22 | + p.reset(); | |
| 23 | + p.addBytes("RIFF".getBytes()) | |
| 24 | + .addBytes(ByteUtils.toLEBytes(len + 36)) | |
| 25 | + .addBytes("WAVE".getBytes()) // wave type | |
| 26 | + .addBytes("fmt ".getBytes()) // fmt id | |
| 27 | + .addInt(0x10000000) // fmt chunk size | |
| 28 | + .addShort((short)0x0100) // format: 1 -> PCM | |
| 29 | + .addShort((short)0x0100) // channels: 1 | |
| 30 | + .addBytes(ByteUtils.toLEBytes(8000)) // samples per second | |
| 31 | + .addBytes(ByteUtils.toLEBytes(1 * 8000 * 16 / 8)) // BPSecond | |
| 32 | + .addBytes(ByteUtils.toLEBytes((short)(1 * 16 / 8))) // BPSample | |
| 33 | + .addBytes(ByteUtils.toLEBytes((short)(1 * 16))) // bPSecond | |
| 34 | + .addBytes("data".getBytes()) // data id | |
| 35 | + .addBytes(ByteUtils.toLEBytes(len)); // data chunk size | |
| 36 | + | |
| 37 | + p.addBytes(block, len); | |
| 38 | + | |
| 39 | + FileOutputStream fos = new FileOutputStream("d:\\fuck.wav"); | |
| 40 | + fos.write(p.getBytes()); | |
| 41 | + fos.flush(); | |
| 42 | + fos.close(); | |
| 43 | + } | |
| 44 | + } | |
| 45 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/ByteBufUtils.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/ByteBufUtils.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +import io.netty.buffer.ByteBuf; | |
| 4 | + | |
| 5 | +import java.nio.charset.StandardCharsets; | |
| 6 | +/** | |
| 7 | + * author:zhouyili (11861744@qq.com) | |
| 8 | + */ | |
| 9 | +public class ByteBufUtils { | |
| 10 | + | |
| 11 | + public static byte[] readReadableBytes(ByteBuf msg) { | |
| 12 | + byte[] content = new byte[msg.readableBytes()]; | |
| 13 | + msg.readBytes(content); | |
| 14 | + return content; | |
| 15 | + } | |
| 16 | + | |
| 17 | + public static byte[] getReadableBytes(ByteBuf msg) { | |
| 18 | + byte[] content = new byte[msg.readableBytes()]; | |
| 19 | + int start = msg.readerIndex(); | |
| 20 | + msg.getBytes(start,content); | |
| 21 | + return content; | |
| 22 | + } | |
| 23 | + public static byte[] readBytes(ByteBuf buf, int length) { | |
| 24 | + validLength(buf, length); | |
| 25 | + byte[] content = new byte[length]; | |
| 26 | + buf.readBytes(content); | |
| 27 | + return content; | |
| 28 | + } | |
| 29 | + | |
| 30 | + private static void validLength(ByteBuf buf, int length) { | |
| 31 | + int readableLength = buf.readableBytes(); | |
| 32 | + if (readableLength<length){ | |
| 33 | + throw new RuntimeException("可读数据长度小于设定值"); | |
| 34 | + } | |
| 35 | + } | |
| 36 | + | |
| 37 | + public static String toString(ByteBuf buf, int length) { | |
| 38 | + validLength(buf,length); | |
| 39 | + return buf.readCharSequence(length, StandardCharsets.ISO_8859_1).toString(); | |
| 40 | + } | |
| 41 | + | |
| 42 | + public static String toString(ByteBuf buf) { | |
| 43 | + return toString(buf,buf.readableBytes()); | |
| 44 | + } | |
| 45 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/ByteHolder.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/ByteHolder.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +import java.util.Arrays; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Created by matrixy on 2018-06-15. | |
| 7 | + */ | |
| 8 | +public class ByteHolder | |
| 9 | +{ | |
| 10 | + int offset = 0; | |
| 11 | + int size = 0; | |
| 12 | + byte[] buffer = null; | |
| 13 | + | |
| 14 | + public ByteHolder(int bufferSize) | |
| 15 | + { | |
| 16 | + this.buffer = new byte[bufferSize]; | |
| 17 | + } | |
| 18 | + | |
| 19 | + public int size() | |
| 20 | + { | |
| 21 | + return this.size; | |
| 22 | + } | |
| 23 | + | |
| 24 | + public void write(byte[] data) | |
| 25 | + { | |
| 26 | + write(data, 0, data.length); | |
| 27 | + } | |
| 28 | + | |
| 29 | + public void write(byte[] data, int offset, int length) | |
| 30 | + { | |
| 31 | + while (this.offset + length >= buffer.length) | |
| 32 | + throw new RuntimeException(String.format("exceed the max buffer size, max length: %d, data length: %d", buffer.length, length)); | |
| 33 | + | |
| 34 | + // 复制一下内容 | |
| 35 | + System.arraycopy(data, offset, buffer, this.offset, length); | |
| 36 | + | |
| 37 | + this.offset += length; | |
| 38 | + this.size += length; | |
| 39 | + } | |
| 40 | + | |
| 41 | + public byte[] array() | |
| 42 | + { | |
| 43 | + return array(this.size); | |
| 44 | + } | |
| 45 | + | |
| 46 | + public byte[] array(int length) | |
| 47 | + { | |
| 48 | + return Arrays.copyOf(this.buffer, length); | |
| 49 | + } | |
| 50 | + | |
| 51 | + public void write(byte b) | |
| 52 | + { | |
| 53 | + this.buffer[offset++] = b; | |
| 54 | + this.size += 1; | |
| 55 | + } | |
| 56 | + | |
| 57 | + public void sliceInto(byte[] dest, int length) | |
| 58 | + { | |
| 59 | + System.arraycopy(this.buffer, 0, dest, 0, length); | |
| 60 | + // 往前挪length个位 | |
| 61 | + System.arraycopy(this.buffer, length, this.buffer, 0, this.size - length); | |
| 62 | + this.offset -= length; | |
| 63 | + this.size -= length; | |
| 64 | + } | |
| 65 | + | |
| 66 | + public void slice(int length) | |
| 67 | + { | |
| 68 | + // 往前挪length个位 | |
| 69 | + System.arraycopy(this.buffer, length, this.buffer, 0, this.size - length); | |
| 70 | + this.offset -= length; | |
| 71 | + this.size -= length; | |
| 72 | + } | |
| 73 | + | |
| 74 | + public byte get(int position) | |
| 75 | + { | |
| 76 | + return this.buffer[position]; | |
| 77 | + } | |
| 78 | + | |
| 79 | + public void clear() | |
| 80 | + { | |
| 81 | + this.offset = 0; | |
| 82 | + this.size = 0; | |
| 83 | + } | |
| 84 | + | |
| 85 | + public int getInt(int offset) | |
| 86 | + { | |
| 87 | + return ByteUtils.getInt(this.buffer, offset, 4); | |
| 88 | + } | |
| 89 | + | |
| 90 | + public int getShort(int position) | |
| 91 | + { | |
| 92 | + int h = this.buffer[position] & 0xff; | |
| 93 | + int l = this.buffer[position + 1] & 0xff; | |
| 94 | + return ((h << 8) | l) & 0xffff; | |
| 95 | + } | |
| 96 | +} | |
| 0 | 97 | \ No newline at end of file | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/ByteUtils.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/ByteUtils.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by matrixy on 2017/8/22. | |
| 5 | + */ | |
| 6 | +public final class ByteUtils | |
| 7 | +{ | |
| 8 | + public static byte[] parse(String hexString) | |
| 9 | + { | |
| 10 | + String[] hexes = hexString.split(" "); | |
| 11 | + byte[] data = new byte[hexes.length]; | |
| 12 | + for (int i = 0; i < hexes.length; i++) data[i] = (byte)(Integer.parseInt(hexes[i], 16) & 0xff); | |
| 13 | + return data; | |
| 14 | + } | |
| 15 | + | |
| 16 | + public static synchronized void dump(byte[] data) | |
| 17 | + { | |
| 18 | + dump(data, data.length); | |
| 19 | + } | |
| 20 | + | |
| 21 | + public static synchronized void dump(byte[] data, int len) | |
| 22 | + { | |
| 23 | + for (int i = 0, l = len; i < l && i < data.length; ) | |
| 24 | + { | |
| 25 | + String ascii = ""; | |
| 26 | + int k = 0, f = 0; | |
| 27 | + for (; k < 16 && k < data.length; k++) | |
| 28 | + { | |
| 29 | + if (k + i < l) | |
| 30 | + { | |
| 31 | + f++; | |
| 32 | + byte d = data[i + k]; | |
| 33 | + String hex = Integer.toHexString(d & 0xff).toUpperCase(); | |
| 34 | + if (hex.length() == 1) hex = "0" + hex; | |
| 35 | + if (d >= 0x20 && d < 127) ascii += (char)d; | |
| 36 | + else ascii += '.'; | |
| 37 | + System.out.print(hex); | |
| 38 | + } | |
| 39 | + else | |
| 40 | + { | |
| 41 | + System.out.print(' '); | |
| 42 | + System.out.print(' '); | |
| 43 | + } | |
| 44 | + | |
| 45 | + if (k % 4 == 3) System.out.print(" "); | |
| 46 | + else System.out.print(' '); | |
| 47 | + } | |
| 48 | + i += f; | |
| 49 | + System.out.println(ascii); | |
| 50 | + } | |
| 51 | + } | |
| 52 | + | |
| 53 | + public static String toString(byte[] data) | |
| 54 | + { | |
| 55 | + if (null == data) return ""; | |
| 56 | + return toString(data, data.length); | |
| 57 | + } | |
| 58 | + | |
| 59 | + public static String toString(byte[] buff, int length) | |
| 60 | + { | |
| 61 | + StringBuffer sb = new StringBuffer(length * 2); | |
| 62 | + for (int i = 0; i < buff.length && i < length; i++) | |
| 63 | + { | |
| 64 | + if ((buff[i] & 0xff) < 0x10) sb.append('0'); | |
| 65 | + sb.append(Integer.toHexString(buff[i] & 0xff).toUpperCase()); | |
| 66 | + sb.append(' '); | |
| 67 | + } | |
| 68 | + return sb.toString(); | |
| 69 | + } | |
| 70 | + | |
| 71 | + public static boolean getBit(int val, int pos) | |
| 72 | + { | |
| 73 | + return getBit(new byte[] { | |
| 74 | + (byte)((val >> 0) & 0xff), | |
| 75 | + (byte)((val >> 8) & 0xff), | |
| 76 | + (byte)((val >> 16) & 0xff), | |
| 77 | + (byte)((val >> 24) & 0xff) | |
| 78 | + }, pos); | |
| 79 | + } | |
| 80 | + | |
| 81 | + public static int reverse(int val) | |
| 82 | + { | |
| 83 | + byte[] bytes = toBytes(val); | |
| 84 | + byte[] ret = new byte[4]; | |
| 85 | + for (int i = 0; i < 4; i++) ret[i] = bytes[3 - i]; | |
| 86 | + return toInt(ret); | |
| 87 | + } | |
| 88 | + | |
| 89 | + public static byte[] toLEBytes(int val) | |
| 90 | + { | |
| 91 | + byte[] bytes = new byte[4]; | |
| 92 | + for (int i = 0; i < 4; i++) | |
| 93 | + { | |
| 94 | + bytes[3 - i] = (byte)(val >> ((3 - i) * 8) & 0xff); | |
| 95 | + } | |
| 96 | + return bytes; | |
| 97 | + } | |
| 98 | + | |
| 99 | + public static byte[] toLEBytes(short s) | |
| 100 | + { | |
| 101 | + byte[] bytes = new byte[2]; | |
| 102 | + bytes[0] = (byte)(s & 0xff); | |
| 103 | + bytes[1] = (byte)((s >> 8) & 0xff); | |
| 104 | + return bytes; | |
| 105 | + } | |
| 106 | + | |
| 107 | + public static int toInt(byte[] bytes) | |
| 108 | + { | |
| 109 | + int val = 0; | |
| 110 | + for (int i = 0; i < 4; i++) val |= (bytes[i] & 0xff) << ((3 - i) * 8); | |
| 111 | + return val; | |
| 112 | + } | |
| 113 | + | |
| 114 | + public static byte[] toBytes(int val) | |
| 115 | + { | |
| 116 | + byte[] bytes = new byte[4]; | |
| 117 | + for (int i = 0; i < 4; i++) | |
| 118 | + { | |
| 119 | + bytes[i] = (byte)(val >> ((3 - i) * 8) & 0xff); | |
| 120 | + } | |
| 121 | + return bytes; | |
| 122 | + } | |
| 123 | + | |
| 124 | + public static byte[] toBytes(long val) | |
| 125 | + { | |
| 126 | + byte[] bytes = new byte[8]; | |
| 127 | + for (int i = 0; i < 8; i++) | |
| 128 | + { | |
| 129 | + bytes[i] = (byte)(val >> ((7 - i) * 8) & 0xff); | |
| 130 | + } | |
| 131 | + return bytes; | |
| 132 | + } | |
| 133 | + | |
| 134 | + public static int getInt(byte[] data, int offset, int length) | |
| 135 | + { | |
| 136 | + int val = 0; | |
| 137 | + for (int i = 0; i < length; i++) val |= (data[offset + i] & 0xff) << ((length - i - 1) * 8); | |
| 138 | + return val; | |
| 139 | + } | |
| 140 | + | |
| 141 | + public static long getLong(byte[] data, int offset, int length) | |
| 142 | + { | |
| 143 | + long val = 0; | |
| 144 | + for (int i = 0; i < length; i++) val |= ((long)data[offset + i] & 0xff) << ((length - i - 1) * 8); | |
| 145 | + return val; | |
| 146 | + } | |
| 147 | + | |
| 148 | + public static boolean getBit(byte[] data, int pos) | |
| 149 | + { | |
| 150 | + return ((data[pos / 8] >> (pos % 8)) & 0x01) == 0x01; | |
| 151 | + } | |
| 152 | + | |
| 153 | + public static byte[] concat(byte[]...byteArrays) | |
| 154 | + { | |
| 155 | + int len = 0, index = 0; | |
| 156 | + for (int i = 0; i < byteArrays.length; i++) len += byteArrays[i].length; | |
| 157 | + byte[] buff = new byte[len]; | |
| 158 | + for (int i = 0; i < byteArrays.length; i++) | |
| 159 | + { | |
| 160 | + System.arraycopy(byteArrays[i], 0, buff, index, byteArrays[i].length); | |
| 161 | + index += byteArrays[i].length; | |
| 162 | + } | |
| 163 | + return buff; | |
| 164 | + } | |
| 165 | + | |
| 166 | + public static boolean compare(byte[] data1, byte[] data2) | |
| 167 | + { | |
| 168 | + if (data1.length != data2.length) return false; | |
| 169 | + for (int i = 0; i < data1.length; i++) | |
| 170 | + if ((data1[i] & 0xff) != (data2[i] & 0xff)) return false; | |
| 171 | + return true; | |
| 172 | + } | |
| 173 | + | |
| 174 | + // 相当于(short *) byte_pointer的效果 | |
| 175 | + public static short[] toShortArray(byte[] src) | |
| 176 | + { | |
| 177 | + short[] dst = new short[src.length / 2]; | |
| 178 | + for (int i = 0, k = 0; i < src.length; ) | |
| 179 | + { | |
| 180 | + dst[k++] = (short)((src[i++] & 0xff) | ((src[i++] & 0xff) << 8)); | |
| 181 | + } | |
| 182 | + return dst; | |
| 183 | + } | |
| 184 | + | |
| 185 | + // 相当于(char *) short_pointer的效果 | |
| 186 | + public static byte[] toByteArray(short[] src) | |
| 187 | + { | |
| 188 | + byte[] dst = new byte[src.length * 2]; | |
| 189 | + for (int i = 0, k = 0; i < src.length; i++) | |
| 190 | + { | |
| 191 | + dst[k++] = (byte)(src[i] & 0xff); | |
| 192 | + dst[k++] = (byte)((src[i] >> 8) & 0xff); | |
| 193 | + } | |
| 194 | + return dst; | |
| 195 | + } | |
| 196 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/Configs.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/Configs.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +import java.io.File; | |
| 4 | +import java.io.FileInputStream; | |
| 5 | +import java.io.IOException; | |
| 6 | +import java.util.Properties; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * Created by matrixy on 2017/8/14. | |
| 10 | + */ | |
| 11 | +public final class Configs | |
| 12 | +{ | |
| 13 | + static Properties properties = new Properties(); | |
| 14 | + | |
| 15 | + public static void init(String configFilePath) | |
| 16 | + { | |
| 17 | + try | |
| 18 | + { | |
| 19 | + File file = new File((configFilePath.startsWith("/") ? "." : "") + configFilePath); | |
| 20 | + if (file.exists()) properties.load(new FileInputStream(file)); | |
| 21 | + else properties.load(Configs.class.getResourceAsStream(configFilePath)); | |
| 22 | + } | |
| 23 | + catch (IOException e) | |
| 24 | + { | |
| 25 | + e.printStackTrace(); | |
| 26 | + } | |
| 27 | + } | |
| 28 | + | |
| 29 | + public static String get(String key) | |
| 30 | + { | |
| 31 | + Object val = properties.get(key); | |
| 32 | + if (null == val) return null; | |
| 33 | + else return String.valueOf(val).trim(); | |
| 34 | + } | |
| 35 | + | |
| 36 | + public static int getInt(String key, int defaultVal) | |
| 37 | + { | |
| 38 | + String val = get(key); | |
| 39 | + if (null == val) return defaultVal; | |
| 40 | + else return Integer.parseInt(val); | |
| 41 | + } | |
| 42 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/FLVUtils.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/FLVUtils.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +import java.util.Arrays; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Created by matrixy on 2019/12/16. | |
| 7 | + */ | |
| 8 | +public final class FLVUtils | |
| 9 | +{ | |
| 10 | + // 重置FLV的时间戳 | |
| 11 | + public static void resetTimestamp(byte[] packet, int timestamp) | |
| 12 | + { | |
| 13 | + // 0 1 2 3 | |
| 14 | + // 4 5 6 7 | |
| 15 | + // 只对视频类的TAG进行修改 | |
| 16 | + if (packet[0] != 9 && packet[0] != 8) return; | |
| 17 | + | |
| 18 | + packet[4] = (byte)((timestamp >> 16) & 0xff); | |
| 19 | + packet[5] = (byte)((timestamp >> 8) & 0xff); | |
| 20 | + packet[6] = (byte)((timestamp >> 0) & 0xff); | |
| 21 | + packet[7] = (byte)((timestamp >> 24) & 0xff); | |
| 22 | + } | |
| 23 | +} | |
| 24 | + | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/FileUtils.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/FileUtils.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +import java.io.*; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Created by matrixy on 2019/8/25. | |
| 7 | + */ | |
| 8 | +public final class FileUtils | |
| 9 | +{ | |
| 10 | + public static void writeFile(File file, byte[] data) | |
| 11 | + { | |
| 12 | + writeFile(file, data, false); | |
| 13 | + } | |
| 14 | + | |
| 15 | + public static void writeFile(File file, byte[] data, boolean append) | |
| 16 | + { | |
| 17 | + FileOutputStream fos = null; | |
| 18 | + try | |
| 19 | + { | |
| 20 | + fos = new FileOutputStream(file, append); | |
| 21 | + fos.write(data); | |
| 22 | + } | |
| 23 | + catch(Exception ex) | |
| 24 | + { | |
| 25 | + throw new RuntimeException(ex); | |
| 26 | + } | |
| 27 | + finally | |
| 28 | + { | |
| 29 | + try { fos.close(); } catch(Exception e) { } | |
| 30 | + } | |
| 31 | + } | |
| 32 | + | |
| 33 | + public static byte[] read(File file) | |
| 34 | + { | |
| 35 | + FileInputStream fis = null; | |
| 36 | + try | |
| 37 | + { | |
| 38 | + fis = new FileInputStream(file); | |
| 39 | + return read(fis); | |
| 40 | + } | |
| 41 | + catch(Exception ex) | |
| 42 | + { | |
| 43 | + throw new RuntimeException(ex); | |
| 44 | + } | |
| 45 | + finally | |
| 46 | + { | |
| 47 | + try { fis.close(); } catch(Exception e) { } | |
| 48 | + } | |
| 49 | + } | |
| 50 | + | |
| 51 | + public static byte[] read(InputStream fis) | |
| 52 | + { | |
| 53 | + ByteArrayOutputStream baos = null; | |
| 54 | + try | |
| 55 | + { | |
| 56 | + baos = new ByteArrayOutputStream(1024); | |
| 57 | + | |
| 58 | + int len = -1; | |
| 59 | + byte[] block = new byte[1024]; | |
| 60 | + while ((len = fis.read(block)) > -1) | |
| 61 | + { | |
| 62 | + baos.write(block, 0, len); | |
| 63 | + } | |
| 64 | + | |
| 65 | + return baos.toByteArray(); | |
| 66 | + } | |
| 67 | + catch(Exception ex) | |
| 68 | + { | |
| 69 | + throw new RuntimeException(ex); | |
| 70 | + } | |
| 71 | + } | |
| 72 | + | |
| 73 | + public static void readInto(File file, OutputStream os) | |
| 74 | + { | |
| 75 | + FileInputStream fis = null; | |
| 76 | + try | |
| 77 | + { | |
| 78 | + int len = -1; | |
| 79 | + byte[] block = new byte[1024]; | |
| 80 | + fis = new FileInputStream(file); | |
| 81 | + while ((len = fis.read(block)) > -1) | |
| 82 | + { | |
| 83 | + os.write(block, 0, len); | |
| 84 | + os.flush(); | |
| 85 | + } | |
| 86 | + } | |
| 87 | + catch(Exception ex) | |
| 88 | + { | |
| 89 | + throw new RuntimeException(ex); | |
| 90 | + } | |
| 91 | + finally | |
| 92 | + { | |
| 93 | + try { fis.close(); } catch(Exception e) { } | |
| 94 | + } | |
| 95 | + } | |
| 96 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/HttpChunk.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/HttpChunk.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by matrixy on 2020/1/15. | |
| 5 | + */ | |
| 6 | +public final class HttpChunk | |
| 7 | +{ | |
| 8 | + public static byte[] make(byte[] data) | |
| 9 | + { | |
| 10 | + Packet p = Packet.create(data.length + 64); | |
| 11 | + p.addBytes(String.format("%x\r\n", data.length).getBytes()); | |
| 12 | + p.addBytes(data); | |
| 13 | + p.addByte((byte)'\r'); | |
| 14 | + p.addByte((byte)'\n'); | |
| 15 | + return p.getBytes(); | |
| 16 | + } | |
| 17 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/Packet.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/Packet.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +import java.util.Arrays; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * Created by matrixy on 2018/4/14. | |
| 7 | + */ | |
| 8 | +public class Packet | |
| 9 | +{ | |
| 10 | + int size = 0; | |
| 11 | + int offset = 0; | |
| 12 | + int maxSize = 0; | |
| 13 | + public byte[] data; | |
| 14 | + | |
| 15 | + protected Packet() | |
| 16 | + { | |
| 17 | + // do nothing here.. | |
| 18 | + } | |
| 19 | + | |
| 20 | + public int size() | |
| 21 | + { | |
| 22 | + return size; | |
| 23 | + } | |
| 24 | + | |
| 25 | + public void resizeTo(int size) | |
| 26 | + { | |
| 27 | + if (this.maxSize >= size) return; | |
| 28 | + byte[] old = Arrays.copyOf(this.data, this.offset); | |
| 29 | + this.data = new byte[size]; | |
| 30 | + System.arraycopy(old, 0, this.data, 0, old.length); | |
| 31 | + } | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 按指定的大小初始化一个数据包,一般大小为2 + 2 + 8 + 4 + DATA_LENGTH | |
| 35 | + * | |
| 36 | + * @param packetLength 数据包最大字节数 | |
| 37 | + * @param bytes | |
| 38 | + * @return | |
| 39 | + */ | |
| 40 | + public static Packet create(int packetLength, byte[] bytes) | |
| 41 | + { | |
| 42 | + Packet p = new Packet(); | |
| 43 | + p.data = new byte[packetLength]; | |
| 44 | + p.maxSize = packetLength; | |
| 45 | + return p; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public static Packet create(int length) | |
| 49 | + { | |
| 50 | + Packet p = new Packet(); | |
| 51 | + p.data = new byte[length]; | |
| 52 | + p.maxSize = length; | |
| 53 | + p.size = 0; | |
| 54 | + p.offset = 0; | |
| 55 | + return p; | |
| 56 | + } | |
| 57 | + | |
| 58 | + public static Packet create(byte[] data) | |
| 59 | + { | |
| 60 | + Packet p = new Packet(); | |
| 61 | + p.data = data; | |
| 62 | + p.maxSize = data.length; | |
| 63 | + p.size = data.length; | |
| 64 | + p.offset = 0; | |
| 65 | + return p; | |
| 66 | + } | |
| 67 | + | |
| 68 | + public Packet addByte(byte b) | |
| 69 | + { | |
| 70 | + this.data[size++] = b; | |
| 71 | + return this; | |
| 72 | + } | |
| 73 | + | |
| 74 | + public Packet add3Bytes(int v) | |
| 75 | + { | |
| 76 | + this.data[size++] = (byte)((v >> 16) & 0xff); | |
| 77 | + this.data[size++] = (byte)((v >> 8) & 0xff); | |
| 78 | + this.data[size++] = (byte)((v >> 0) & 0xff); | |
| 79 | + return this; | |
| 80 | + } | |
| 81 | + | |
| 82 | + // 如果b的值为0x7e,则自动转义 | |
| 83 | + public Packet addByteAutoQuote(byte b) | |
| 84 | + { | |
| 85 | + if (b == 0x7e) | |
| 86 | + { | |
| 87 | + addByte((byte)0x7d); | |
| 88 | + addByte((byte)0x02); | |
| 89 | + } | |
| 90 | + else if (b == 0x7d) | |
| 91 | + { | |
| 92 | + addByte((byte)0x7d); | |
| 93 | + addByte((byte)0x01); | |
| 94 | + } | |
| 95 | + else | |
| 96 | + { | |
| 97 | + addByte(b); | |
| 98 | + } | |
| 99 | + return this; | |
| 100 | + } | |
| 101 | + | |
| 102 | + public Packet putByte(byte b) | |
| 103 | + { | |
| 104 | + this.data[offset++] = b; | |
| 105 | + return this; | |
| 106 | + } | |
| 107 | + | |
| 108 | + public Packet addShort(short s) | |
| 109 | + { | |
| 110 | + this.data[size++] = (byte) ((s >> 8) & 0xff); | |
| 111 | + this.data[size++] = (byte) (s & 0xff); | |
| 112 | + return this; | |
| 113 | + } | |
| 114 | + | |
| 115 | + public Packet putShort(short s) | |
| 116 | + { | |
| 117 | + this.data[offset++] = (byte) ((s >> 8) & 0xff); | |
| 118 | + this.data[offset++] = (byte) (s & 0xff); | |
| 119 | + return this; | |
| 120 | + } | |
| 121 | + | |
| 122 | + public Packet addInt(int i) | |
| 123 | + { | |
| 124 | + this.data[size++] = (byte) ((i >> 24) & 0xff); | |
| 125 | + this.data[size++] = (byte) ((i >> 16) & 0xff); | |
| 126 | + this.data[size++] = (byte) ((i >> 8) & 0xff); | |
| 127 | + this.data[size++] = (byte) (i & 0xff); | |
| 128 | + return this; | |
| 129 | + } | |
| 130 | + | |
| 131 | + public Packet putInt(int i) | |
| 132 | + { | |
| 133 | + this.data[offset++] = (byte) ((i >> 24) & 0xff); | |
| 134 | + this.data[offset++] = (byte) ((i >> 16) & 0xff); | |
| 135 | + this.data[offset++] = (byte) ((i >> 8) & 0xff); | |
| 136 | + this.data[offset++] = (byte) (i & 0xff); | |
| 137 | + return this; | |
| 138 | + } | |
| 139 | + | |
| 140 | + public Packet addLong(long l) | |
| 141 | + { | |
| 142 | + this.data[size++] = (byte) ((l >> 56) & 0xff); | |
| 143 | + this.data[size++] = (byte) ((l >> 48) & 0xff); | |
| 144 | + this.data[size++] = (byte) ((l >> 40) & 0xff); | |
| 145 | + this.data[size++] = (byte) ((l >> 32) & 0xff); | |
| 146 | + this.data[size++] = (byte) ((l >> 24) & 0xff); | |
| 147 | + this.data[size++] = (byte) ((l >> 16) & 0xff); | |
| 148 | + this.data[size++] = (byte) ((l >> 8) & 0xff); | |
| 149 | + this.data[size++] = (byte) (l & 0xff); | |
| 150 | + return this; | |
| 151 | + } | |
| 152 | + | |
| 153 | + public Packet putLong(long l) | |
| 154 | + { | |
| 155 | + this.data[offset++] = (byte) ((l >> 56) & 0xff); | |
| 156 | + this.data[offset++] = (byte) ((l >> 48) & 0xff); | |
| 157 | + this.data[offset++] = (byte) ((l >> 40) & 0xff); | |
| 158 | + this.data[offset++] = (byte) ((l >> 32) & 0xff); | |
| 159 | + this.data[offset++] = (byte) ((l >> 24) & 0xff); | |
| 160 | + this.data[offset++] = (byte) ((l >> 16) & 0xff); | |
| 161 | + this.data[offset++] = (byte) ((l >> 8) & 0xff); | |
| 162 | + this.data[offset++] = (byte) (l & 0xff); | |
| 163 | + return this; | |
| 164 | + } | |
| 165 | + | |
| 166 | + public Packet addBytes(byte[] b) | |
| 167 | + { | |
| 168 | + return addBytes(b, b.length); | |
| 169 | + } | |
| 170 | + | |
| 171 | + public Packet addBytes(byte[] b, int len) | |
| 172 | + { | |
| 173 | + System.arraycopy(b, 0, this.data, size, len); | |
| 174 | + size += len; | |
| 175 | + return this; | |
| 176 | + } | |
| 177 | + | |
| 178 | + public Packet putBytes(byte[] b) | |
| 179 | + { | |
| 180 | + System.arraycopy(b, 0, this.data, offset, b.length); | |
| 181 | + offset += b.length; | |
| 182 | + return this; | |
| 183 | + } | |
| 184 | + | |
| 185 | + public Packet rewind() | |
| 186 | + { | |
| 187 | + this.offset = 0; | |
| 188 | + return this; | |
| 189 | + } | |
| 190 | + | |
| 191 | + public byte nextByte() | |
| 192 | + { | |
| 193 | + return this.data[offset++]; | |
| 194 | + } | |
| 195 | + | |
| 196 | + public short nextShort() | |
| 197 | + { | |
| 198 | + return (short) (((this.data[offset++] & 0xff) << 8) | (this.data[offset++] & 0xff)); | |
| 199 | + } | |
| 200 | + | |
| 201 | + public short nextWord() | |
| 202 | + { | |
| 203 | + return nextShort(); | |
| 204 | + } | |
| 205 | + | |
| 206 | + public int nextDWord() | |
| 207 | + { | |
| 208 | + return nextInt(); | |
| 209 | + } | |
| 210 | + | |
| 211 | + public int nextInt() | |
| 212 | + { | |
| 213 | + return (this.data[offset++] & 0xff) << 24 | (this.data[offset++] & 0xff) << 16 | (this.data[offset++] & 0xff) << 8 | (this.data[offset++] & 0xff); | |
| 214 | + } | |
| 215 | + | |
| 216 | + public String nextBCD() | |
| 217 | + { | |
| 218 | + byte val = this.data[offset++]; | |
| 219 | + int ch1 = (val >> 4) & 0x0f; | |
| 220 | + int ch2 = (val & 0x0f); | |
| 221 | + return ch1 + "" + ch2; | |
| 222 | + } | |
| 223 | + | |
| 224 | + public Packet addBCD(String num) | |
| 225 | + { | |
| 226 | + for (int i = 0, l = num.length(); i < l; i+=2) | |
| 227 | + { | |
| 228 | + char a = (char)(num.charAt(i) - '0'); | |
| 229 | + char b = (char)(num.charAt(i + 1) - '0'); | |
| 230 | + addByte((byte)(a << 4 | b)); | |
| 231 | + } | |
| 232 | + return this; | |
| 233 | + } | |
| 234 | + | |
| 235 | + public long nextLong() | |
| 236 | + { | |
| 237 | + return ((long) this.data[offset++] & 0xff) << 56 | ((long) this.data[offset++] & 0xff) << 48 | ((long) this.data[offset++] & 0xff) << 40 | ((long) this.data[offset++] & 0xff) << 32 | ((long) this.data[offset++] & 0xff) << 24 | ((long) this.data[offset++] & 0xff) << 16 | ((long) this.data[offset++] & 0xff) << 8 | ((long) this.data[offset++] & 0xff); | |
| 238 | + } | |
| 239 | + | |
| 240 | + public byte[] nextBytes(int length) | |
| 241 | + { | |
| 242 | + byte[] buf = new byte[length]; | |
| 243 | + System.arraycopy(this.data, offset, buf, 0, length); | |
| 244 | + offset += length; | |
| 245 | + return buf; | |
| 246 | + } | |
| 247 | + | |
| 248 | + public byte[] nextBytes() | |
| 249 | + { | |
| 250 | + return nextBytes(size - offset); | |
| 251 | + } | |
| 252 | + | |
| 253 | + public Packet skip(int offset) | |
| 254 | + { | |
| 255 | + this.offset += offset; | |
| 256 | + return this; | |
| 257 | + } | |
| 258 | + | |
| 259 | + public Packet seek(int index) | |
| 260 | + { | |
| 261 | + this.offset = index; | |
| 262 | + return this; | |
| 263 | + } | |
| 264 | + | |
| 265 | + public Packet reset() | |
| 266 | + { | |
| 267 | + this.offset = 0; | |
| 268 | + this.size = 0; | |
| 269 | + | |
| 270 | + return this; | |
| 271 | + } | |
| 272 | + | |
| 273 | + public byte[] getBytes() | |
| 274 | + { | |
| 275 | + if (size == maxSize) return this.data; | |
| 276 | + else | |
| 277 | + { | |
| 278 | + byte[] buff = new byte[size]; | |
| 279 | + System.arraycopy(this.data, 0, buff, 0, size); | |
| 280 | + return buff; | |
| 281 | + } | |
| 282 | + } | |
| 283 | + | |
| 284 | + public boolean hasMoreBytes() | |
| 285 | + { | |
| 286 | + return size - offset > 0; | |
| 287 | + } | |
| 288 | + | |
| 289 | + public static void main(String[] args) throws Exception | |
| 290 | + { | |
| 291 | + ByteUtils.dump(Packet.create(32).addBCD("013800138000").getBytes()); | |
| 292 | + } | |
| 293 | +} | ... | ... |
src/main/java/cn/org/hentai/jtt1078/util/WAVUtils.java
0 → 100644
| 1 | +++ a/src/main/java/cn/org/hentai/jtt1078/util/WAVUtils.java | |
| 1 | +package cn.org.hentai.jtt1078.util; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by matrixy on 2019/12/18. | |
| 5 | + */ | |
| 6 | +public final class WAVUtils | |
| 7 | +{ | |
| 8 | + /** | |
| 9 | + * 创建WAV头,仅返回WAV头部字节数组信息 | |
| 10 | + * @param dataLength PCM数据字节总 | |
| 11 | + * @param channels 通道数,通常为1 | |
| 12 | + * @param sampleRate 采样率,通常为8000 | |
| 13 | + * @param sampleBits 样本比特位数,通常为16 | |
| 14 | + * @return | |
| 15 | + */ | |
| 16 | + public static byte[] createHeader(int dataLength, int channels, int sampleRate, int sampleBits) | |
| 17 | + { | |
| 18 | + Packet p = Packet.create(44); | |
| 19 | + p.addBytes("RIFF".getBytes()) | |
| 20 | + .addBytes(ByteUtils.toLEBytes(dataLength + 36)) | |
| 21 | + .addBytes("WAVE".getBytes()) // wave type | |
| 22 | + .addBytes("fmt ".getBytes()) // fmt id | |
| 23 | + .addInt(0x10000000) // fmt chunk size | |
| 24 | + .addShort((short)0x0100) // format: 1 -> PCM | |
| 25 | + .addBytes(ByteUtils.toLEBytes((short)channels)) // channels: 1 | |
| 26 | + .addBytes(ByteUtils.toLEBytes(sampleRate)) // samples per second | |
| 27 | + .addBytes(ByteUtils.toLEBytes(1 * sampleRate * sampleBits / 8)) // BPSecond | |
| 28 | + .addBytes(ByteUtils.toLEBytes((short)(1 * sampleBits / 8))) // BPSample | |
| 29 | + .addBytes(ByteUtils.toLEBytes((short)(1 * sampleBits))) // bPSecond | |
| 30 | + .addBytes("data".getBytes()) // data id | |
| 31 | + .addBytes(ByteUtils.toLEBytes(dataLength)); // data chunk size | |
| 32 | + | |
| 33 | + return p.getBytes(); | |
| 34 | + } | |
| 35 | +} | ... | ... |
src/main/resources/app.properties
0 → 100644
| 1 | +++ a/src/main/resources/app.properties | |
| 1 | +server.port = 1078 | |
| 2 | +server.http.port = 3333 | |
| 3 | +server.backlog = 1024 | |
| 4 | + | |
| 5 | +# ffmpeg可执行文件路径,可以留空 | |
| 6 | +ffmpeg.path = D:/Tools/ffmpeg-4.2.2-win64-static/bin/ffmpeg.exe | |
| 7 | + | |
| 8 | +# 配置rtmp地址将在终端发送RTP消息包时,额外的向RTMP服务器推流 | |
| 9 | +# TAG的形式就是SIM-CHANNEL,如13800138999-2 | |
| 10 | +# 如果留空将不向RTMP服务器推流 | |
| 11 | +# rtmp.url = rtmp://192.168.0.2/live/{TAG} | |
| 12 | + | |
| 13 | +# 设置为on时,控制台将输出ffmpeg的输出 | |
| 14 | +debug.mode = off | |
| 0 | 15 | \ No newline at end of file | ... | ... |
src/main/resources/audio.html
0 → 100644
| 1 | +++ a/src/main/resources/audio.html | |
| 1 | +<html> | |
| 2 | + <head> | |
| 3 | + <title>Chunked Audio Test</title> | |
| 4 | + </head> | |
| 5 | + <body> | |
| 6 | + <button>Play</button> | |
| 7 | + </body> | |
| 8 | +</html> | |
| 9 | +<script src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js" type="text/javascript"></script> | |
| 10 | +<script type="text/javascript"> | |
| 11 | + | |
| 12 | + var streamOffset = 0; | |
| 13 | + var Base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); | |
| 14 | + var CharIdxArray = { }; | |
| 15 | + for (var i = 0; i < Base64Chars.length; i++) CharIdxArray[Base64Chars[i]] = i; | |
| 16 | + | |
| 17 | + window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext; | |
| 18 | + var audioContext = new AudioContext(); | |
| 19 | + var segments = []; | |
| 20 | + var ended = true; | |
| 21 | + | |
| 22 | + function playNextSegment() | |
| 23 | + { | |
| 24 | + if (segments.length > 0 && ended) | |
| 25 | + { | |
| 26 | + ended = false; | |
| 27 | + var audioBufferSouceNode = audioContext.createBufferSource(); | |
| 28 | + audioBufferSouceNode.onended = function() | |
| 29 | + { | |
| 30 | + // playNextSegment(); | |
| 31 | + ended = true; | |
| 32 | + console.log('play ended...'); | |
| 33 | + } | |
| 34 | + audioBufferSouceNode.buffer = segments.shift(); | |
| 35 | + audioBufferSouceNode.connect(audioContext.destination); | |
| 36 | + audioBufferSouceNode.start(0); | |
| 37 | + } | |
| 38 | + } | |
| 39 | + | |
| 40 | + $(document).ready(function() | |
| 41 | + { | |
| 42 | + var decodeCallback = function(buffer) | |
| 43 | + { | |
| 44 | + segments.push(buffer); | |
| 45 | + }; | |
| 46 | + | |
| 47 | + $('button').click(function() | |
| 48 | + { | |
| 49 | + var xhr = new XMLHttpRequest(); | |
| 50 | + xhr.open('GET', '/audio/' + location.hash.substring(1), true); | |
| 51 | + xhr.onprogress = function() | |
| 52 | + { | |
| 53 | + var audioData = xhr.responseText; | |
| 54 | + while (true) | |
| 55 | + { | |
| 56 | + var audio = base64Decode(audioData); | |
| 57 | + if (audio == null) break; | |
| 58 | + console.log('decoded: ' + audio.length); | |
| 59 | + audioContext.decodeAudioData(audio.buffer, decodeCallback); | |
| 60 | + } | |
| 61 | + } | |
| 62 | + xhr.send(); | |
| 63 | + }); | |
| 64 | + | |
| 65 | + setInterval(playNextSegment, 50); | |
| 66 | + }); | |
| 67 | + | |
| 68 | + function base64Decode(text) | |
| 69 | + { | |
| 70 | + var i, k = 0, l; | |
| 71 | + if (text.length < streamOffset + 8) return null; | |
| 72 | + var blockLength = parseInt(text.substring(streamOffset, streamOffset + 8), 16); | |
| 73 | + console.log('block: ' + blockLength); | |
| 74 | + if (text.length < streamOffset + 8 + blockLength) return null; | |
| 75 | + | |
| 76 | + var audioBuffer = new Uint8Array(new ArrayBuffer(2048), 0); | |
| 77 | + for (i = streamOffset + 8, l = text.length; i < l && k < blockLength; ) | |
| 78 | + { | |
| 79 | + var a = CharIdxArray[text.charAt(i + 0)]; | |
| 80 | + var b = CharIdxArray[text.charAt(i + 1)]; | |
| 81 | + var c = CharIdxArray[text.charAt(i + 2)]; | |
| 82 | + var d = CharIdxArray[text.charAt(i + 3)]; | |
| 83 | + | |
| 84 | + var b1 = ((a << 2) | (b >> 4)) & 0xff; | |
| 85 | + var b2 = ((b << 4) | (c >> 2)) & 0xff; | |
| 86 | + var b3 = ((c << 6) | (d)) & 0xff; | |
| 87 | + | |
| 88 | + audioBuffer[k++] = b1; | |
| 89 | + audioBuffer[k++] = b2; | |
| 90 | + audioBuffer[k++] = b3; | |
| 91 | + | |
| 92 | + i += 4; | |
| 93 | + } | |
| 94 | + streamOffset += blockLength + 8; | |
| 95 | + | |
| 96 | + /* | |
| 97 | + var hex = []; | |
| 98 | + for (i = 0; i < k && i < 32; i++) | |
| 99 | + { | |
| 100 | + var ch = (audioBuffer[i] & 0xff).toString(16).toUpperCase(); | |
| 101 | + hex.push(ch.length == 1 ? '0' + ch : ch); | |
| 102 | + hex.push(' '); | |
| 103 | + if (i % 4 == 3) hex.push(" "); | |
| 104 | + if (i % 16 == 15) hex.push("\n"); | |
| 105 | + } | |
| 106 | + console.log(hex.join('')); | |
| 107 | + */ | |
| 108 | + | |
| 109 | + return audioBuffer.subarray(k); | |
| 110 | + } | |
| 111 | + | |
| 112 | +</script> | ... | ... |
src/main/resources/flv.min.js
0 → 100644
| 1 | +++ a/src/main/resources/flv.min.js | |
| 1 | +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.flvjs=e()}}(function(){var e;return function e(t,n,i){function r(a,o){if(!n[a]){if(!t[a]){var u="function"==typeof require&&require;if(!o&&u)return u(a,!0);if(s)return s(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var d=n[a]={exports:{}};t[a][0].call(d.exports,function(e){var n=t[a][1][e];return r(n||e)},d,d.exports,e,t,n,i)}return n[a].exports}for(var s="function"==typeof require&&require,a=0;a<i.length;a++)r(i[a]);return r}({1:[function(t,n,i){(function(r,s){!function(t,r){"object"==typeof i&&void 0!==n?n.exports=r():"function"==typeof e&&e.amd?e(r):t.ES6Promise=r()}(this,function(){"use strict";function e(e){var t=typeof e;return null!==e&&("object"===t||"function"===t)}function n(e){return"function"==typeof e}function i(e){V=e}function a(e){z=e}function o(){return void 0!==G?function(){G(l)}:u()}function u(){var e=setTimeout;return function(){return e(l,1)}}function l(){for(var e=0;e<F;e+=2){(0,Y[e])(Y[e+1]),Y[e]=void 0,Y[e+1]=void 0}F=0}function d(e,t){var n=this,i=new this.constructor(f);void 0===i[Q]&&C(i);var r=n._state;if(r){var s=arguments[r-1];z(function(){return w(r,i,s,n._result)})}else L(n,i,e,t);return i}function h(e){var t=this;if(e&&"object"==typeof e&&e.constructor===t)return e;var n=new t(f);return E(n,e),n}function f(){}function c(){return new TypeError("You cannot resolve a promise with itself")}function _(){return new TypeError("A promises callback cannot return that same promise.")}function m(e){try{return e.then}catch(e){return te.error=e,te}}function p(e,t,n,i){try{e.call(t,n,i)}catch(e){return e}}function v(e,t,n){z(function(e){var i=!1,r=p(n,t,function(n){i||(i=!0,t!==n?E(e,n):S(e,n))},function(t){i||(i=!0,k(e,t))},"Settle: "+(e._label||" unknown promise"));!i&&r&&(i=!0,k(e,r))},e)}function g(e,t){t._state===$?S(e,t._result):t._state===ee?k(e,t._result):L(t,void 0,function(t){return E(e,t)},function(t){return k(e,t)})}function y(e,t,i){t.constructor===e.constructor&&i===d&&t.constructor.resolve===h?g(e,t):i===te?(k(e,te.error),te.error=null):void 0===i?S(e,t):n(i)?v(e,t,i):S(e,t)}function E(t,n){t===n?k(t,c()):e(n)?y(t,n,m(n)):S(t,n)}function b(e){e._onerror&&e._onerror(e._result),R(e)}function S(e,t){e._state===J&&(e._result=t,e._state=$,0!==e._subscribers.length&&z(R,e))}function k(e,t){e._state===J&&(e._state=ee,e._result=t,z(b,e))}function L(e,t,n,i){var r=e._subscribers,s=r.length;e._onerror=null,r[s]=t,r[s+$]=n,r[s+ee]=i,0===s&&e._state&&z(R,e)}function R(e){var t=e._subscribers,n=e._state;if(0!==t.length){for(var i=void 0,r=void 0,s=e._result,a=0;a<t.length;a+=3)i=t[a],r=t[a+n],i?w(n,i,r,s):r(s);e._subscribers.length=0}}function A(e,t){try{return e(t)}catch(e){return te.error=e,te}}function w(e,t,i,r){var s=n(i),a=void 0,o=void 0,u=void 0,l=void 0;if(s){if(a=A(i,r),a===te?(l=!0,o=a.error,a.error=null):u=!0,t===a)return void k(t,_())}else a=r,u=!0;t._state!==J||(s&&u?E(t,a):l?k(t,o):e===$?S(t,a):e===ee&&k(t,a))}function T(e,t){try{t(function(t){E(e,t)},function(t){k(e,t)})}catch(t){k(e,t)}}function O(){return ne++}function C(e){e[Q]=ne++,e._state=void 0,e._result=void 0,e._subscribers=[]}function I(){return new Error("Array Methods must be provided an Array")}function D(e){return new ie(this,e).promise}function x(e){var t=this;return new t(N(e)?function(n,i){for(var r=e.length,s=0;s<r;s++)t.resolve(e[s]).then(n,i)}:function(e,t){return t(new TypeError("You must pass an array to race."))})}function M(e){var t=this,n=new t(f);return k(n,e),n}function B(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function j(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function P(){var e=void 0;if(void 0!==s)e=s;else if("undefined"!=typeof self)e=self;else try{e=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var t=e.Promise;if(t){var n=null;try{n=Object.prototype.toString.call(t.resolve())}catch(e){}if("[object Promise]"===n&&!t.cast)return}e.Promise=re}var U=void 0;U=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var N=U,F=0,G=void 0,V=void 0,z=function(e,t){Y[F]=e,Y[F+1]=t,2===(F+=2)&&(V?V(l):Z())},H="undefined"!=typeof window?window:void 0,K=H||{},q=K.MutationObserver||K.WebKitMutationObserver,W="undefined"==typeof self&&void 0!==r&&"[object process]"==={}.toString.call(r),X="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,Y=new Array(1e3),Z=void 0;Z=W?function(){return function(){return r.nextTick(l)}}():q?function(){var e=0,t=new q(l),n=document.createTextNode("");return t.observe(n,{characterData:!0}),function(){n.data=e=++e%2}}():X?function(){var e=new MessageChannel;return e.port1.onmessage=l,function(){return e.port2.postMessage(0)}}():void 0===H&&"function"==typeof t?function(){try{var e=Function("return this")().require("vertx");return G=e.runOnLoop||e.runOnContext,o()}catch(e){return u()}}():u();var Q=Math.random().toString(36).substring(2),J=void 0,$=1,ee=2,te={error:null},ne=0,ie=function(){function e(e,t){this._instanceConstructor=e,this.promise=new e(f),this.promise[Q]||C(this.promise),N(t)?(this.length=t.length,this._remaining=t.length,this._result=new Array(this.length),0===this.length?S(this.promise,this._result):(this.length=this.length||0,this._enumerate(t),0===this._remaining&&S(this.promise,this._result))):k(this.promise,I())}return e.prototype._enumerate=function(e){for(var t=0;this._state===J&&t<e.length;t++)this._eachEntry(e[t],t)},e.prototype._eachEntry=function(e,t){var n=this._instanceConstructor,i=n.resolve;if(i===h){var r=m(e);if(r===d&&e._state!==J)this._settledAt(e._state,t,e._result);else if("function"!=typeof r)this._remaining--,this._result[t]=e;else if(n===re){var s=new n(f);y(s,e,r),this._willSettleAt(s,t)}else this._willSettleAt(new n(function(t){return t(e)}),t)}else this._willSettleAt(i(e),t)},e.prototype._settledAt=function(e,t,n){var i=this.promise;i._state===J&&(this._remaining--,e===ee?k(i,n):this._result[t]=n),0===this._remaining&&S(i,this._result)},e.prototype._willSettleAt=function(e,t){var n=this;L(e,void 0,function(e){return n._settledAt($,t,e)},function(e){return n._settledAt(ee,t,e)})},e}(),re=function(){function e(t){this[Q]=O(),this._result=this._state=void 0,this._subscribers=[],f!==t&&("function"!=typeof t&&B(),this instanceof e?T(this,t):j())}return e.prototype.catch=function(e){return this.then(null,e)},e.prototype.finally=function(e){var t=this,i=t.constructor;return n(e)?t.then(function(t){return i.resolve(e()).then(function(){return t})},function(t){return i.resolve(e()).then(function(){throw t})}):t.then(e,e)},e}();return re.prototype.then=d,re.all=D,re.race=x,re.resolve=h,re.reject=M,re._setScheduler=i,re._setAsap=a,re._asap=z,re.polyfill=P,re.Promise=re,re})}).call(this,t("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:3}],2:[function(e,t,n){function i(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return"function"==typeof e}function s(e){return"number"==typeof e}function a(e){return"object"==typeof e&&null!==e}function o(e){return void 0===e}t.exports=i,i.EventEmitter=i,i.prototype._events=void 0,i.prototype._maxListeners=void 0,i.defaultMaxListeners=10,i.prototype.setMaxListeners=function(e){if(!s(e)||e<0||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},i.prototype.emit=function(e){var t,n,i,s,u,l;if(this._events||(this._events={}),"error"===e&&(!this._events.error||a(this._events.error)&&!this._events.error.length)){if((t=arguments[1])instanceof Error)throw t;var d=new Error('Uncaught, unspecified "error" event. ('+t+")");throw d.context=t,d}if(n=this._events[e],o(n))return!1;if(r(n))switch(arguments.length){case 1:n.call(this);break;case 2:n.call(this,arguments[1]);break;case 3:n.call(this,arguments[1],arguments[2]);break;default:s=Array.prototype.slice.call(arguments,1),n.apply(this,s)}else if(a(n))for(s=Array.prototype.slice.call(arguments,1),l=n.slice(),i=l.length,u=0;u<i;u++)l[u].apply(this,s);return!0},i.prototype.addListener=function(e,t){var n;if(!r(t))throw TypeError("listener must be a function");return this._events||(this._events={}),this._events.newListener&&this.emit("newListener",e,r(t.listener)?t.listener:t),this._events[e]?a(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t,a(this._events[e])&&!this._events[e].warned&&(n=o(this._maxListeners)?i.defaultMaxListeners:this._maxListeners)&&n>0&&this._events[e].length>n&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace()),this},i.prototype.on=i.prototype.addListener,i.prototype.once=function(e,t){function n(){this.removeListener(e,n),i||(i=!0,t.apply(this,arguments))}if(!r(t))throw TypeError("listener must be a function");var i=!1;return n.listener=t,this.on(e,n),this},i.prototype.removeListener=function(e,t){var n,i,s,o;if(!r(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(n=this._events[e],s=n.length,i=-1,n===t||r(n.listener)&&n.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(a(n)){for(o=s;o-- >0;)if(n[o]===t||n[o].listener&&n[o].listener===t){i=o;break}if(i<0)return this;1===n.length?(n.length=0,delete this._events[e]):n.splice(i,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},i.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(n=this._events[e],r(n))this.removeListener(e,n);else if(n)for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},i.prototype.listeners=function(e){return this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},i.prototype.listenerCount=function(e){if(this._events){var t=this._events[e];if(r(t))return 1;if(t)return t.length}return 0},i.listenerCount=function(e,t){return e.listenerCount(t)}},{}],3:[function(e,t,n){function i(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function s(e){if(h===setTimeout)return setTimeout(e,0);if((h===i||!h)&&setTimeout)return h=setTimeout,setTimeout(e,0);try{return h(e,0)}catch(t){try{return h.call(null,e,0)}catch(t){return h.call(this,e,0)}}}function a(e){if(f===clearTimeout)return clearTimeout(e);if((f===r||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(e);try{return f(e)}catch(t){try{return f.call(null,e)}catch(t){return f.call(this,e)}}}function o(){p&&_&&(p=!1,_.length?m=_.concat(m):v=-1,m.length&&u())}function u(){if(!p){var e=s(o);p=!0;for(var t=m.length;t;){for(_=m,m=[];++v<t;)_&&_[v].run();v=-1,t=m.length}_=null,p=!1,a(e)}}function l(e,t){this.fun=e,this.array=t}function d(){}var h,f,c=t.exports={};!function(){try{h="function"==typeof setTimeout?setTimeout:i}catch(e){h=i}try{f="function"==typeof clearTimeout?clearTimeout:r}catch(e){f=r}}();var _,m=[],p=!1,v=-1;c.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];m.push(new l(e,t)),1!==m.length||p||s(u)},l.prototype.run=function(){this.fun.apply(null,this.array)},c.title="browser",c.browser=!0,c.env={},c.argv=[],c.version="",c.versions={},c.on=d,c.addListener=d,c.once=d,c.off=d,c.removeListener=d,c.removeAllListeners=d,c.emit=d,c.prependListener=d,c.prependOnceListener=d,c.listeners=function(e){return[]},c.binding=function(e){throw new Error("process.binding is not supported")},c.cwd=function(){return"/"},c.chdir=function(e){throw new Error("process.chdir is not supported")},c.umask=function(){return 0}},{}],4:[function(e,t,n){var i=arguments[3],r=arguments[4],s=arguments[5],a=JSON.stringify;t.exports=function(e,t){function n(e){p[e]=!0;for(var t in r[e][1]){var i=r[e][1][t];p[i]||n(i)}}for(var o,u=Object.keys(s),l=0,d=u.length;l<d;l++){var h=u[l],f=s[h].exports;if(f===e||f&&f.default===e){o=h;break}}if(!o){o=Math.floor(Math.pow(16,8)*Math.random()).toString(16);for(var c={},l=0,d=u.length;l<d;l++){var h=u[l];c[h]=h}r[o]=["function(require,module,exports){"+e+"(self); }",c]}var _=Math.floor(Math.pow(16,8)*Math.random()).toString(16),m={};m[o]=o,r[_]=["function(require,module,exports){var f = require("+a(o)+");(f.default ? f.default : f)(self);}",m];var p={};n(_);var v="("+i+")({"+Object.keys(p).map(function(e){return a(e)+":["+r[e][0]+","+a(r[e][1])+"]"}).join(",")+"},{},["+a(_)+"])",g=window.URL||window.webkitURL||window.mozURL||window.msURL,y=new Blob([v],{type:"text/javascript"});if(t&&t.bare)return y;var E=g.createObjectURL(y),b=new Worker(E);return b.objectURL=E,b}},{}],5:[function(e,t,n){"use strict";function i(){return Object.assign({},r)}Object.defineProperty(n,"__esModule",{value:!0}),n.createDefaultConfig=i;var r=n.defaultConfig={enableWorker:!1,enableStashBuffer:!0,stashInitialSize:void 0,isLive:!1,lazyLoad:!0,lazyLoadMaxDuration:180,lazyLoadRecoverDuration:30,deferLoadAfterSourceOpen:!0,autoCleanupMaxBackwardDuration:180,autoCleanupMinBackwardDuration:120,statisticsInfoReportInterval:600,fixAudioTimestampGap:!0,accurateSeek:!1,seekType:"range",seekParamStart:"bstart",seekParamEnd:"bend",rangeLoadZeroStart:!1,customSeekHandler:void 0,reuseRedirectedURL:!1,headers:void 0,customLoader:void 0}},{}],6:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("../io/io-controller.js"),a=function(e){return e&&e.__esModule?e:{default:e}}(s),o=e("../config.js"),u=function(){function e(){i(this,e)}return r(e,null,[{key:"supportMSEH264Playback",value:function(){return window.MediaSource&&window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"')}},{key:"supportNetworkStreamIO",value:function(){var e=new a.default({},(0,o.createDefaultConfig)()),t=e.loaderType;return e.destroy(),"fetch-stream-loader"==t||"xhr-moz-chunked-loader"==t}},{key:"getNetworkLoaderTypeName",value:function(){var e=new a.default({},(0,o.createDefaultConfig)()),t=e.loaderType;return e.destroy(),t}},{key:"supportNativeMediaPlayback",value:function(t){void 0==e.videoElement&&(e.videoElement=window.document.createElement("video"));var n=e.videoElement.canPlayType(t);return"probably"===n||"maybe"==n}},{key:"getFeatureList",value:function(){var t={mseFlvPlayback:!1,mseLiveFlvPlayback:!1,networkStreamIO:!1,networkLoaderName:"",nativeMP4H264Playback:!1,nativeWebmVP8Playback:!1,nativeWebmVP9Playback:!1};return t.mseFlvPlayback=e.supportMSEH264Playback(),t.networkStreamIO=e.supportNetworkStreamIO(),t.networkLoaderName=e.getNetworkLoaderTypeName(),t.mseLiveFlvPlayback=t.mseFlvPlayback&&t.networkStreamIO,t.nativeMP4H264Playback=e.supportNativeMediaPlayback('video/mp4; codecs="avc1.42001E, mp4a.40.2"'),t.nativeWebmVP8Playback=e.supportNativeMediaPlayback('video/webm; codecs="vp8.0, vorbis"'),t.nativeWebmVP9Playback=e.supportNativeMediaPlayback('video/webm; codecs="vp9"'),t}}]),e}();n.default=u},{"../config.js":5,"../io/io-controller.js":23}],7:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(){i(this,e),this.mimeType=null,this.duration=null,this.hasAudio=null,this.hasVideo=null,this.audioCodec=null,this.videoCodec=null,this.audioDataRate=null,this.videoDataRate=null,this.audioSampleRate=null,this.audioChannelCount=null,this.width=null,this.height=null,this.fps=null,this.profile=null,this.level=null,this.refFrames=null,this.chromaFormat=null,this.sarNum=null,this.sarDen=null,this.metadata=null,this.segments=null,this.segmentCount=null,this.hasKeyframesIndex=null,this.keyframesIndex=null}return r(e,[{key:"isComplete",value:function(){var e=!1===this.hasAudio||!0===this.hasAudio&&null!=this.audioCodec&&null!=this.audioSampleRate&&null!=this.audioChannelCount,t=!1===this.hasVideo||!0===this.hasVideo&&null!=this.videoCodec&&null!=this.width&&null!=this.height&&null!=this.fps&&null!=this.profile&&null!=this.level&&null!=this.refFrames&&null!=this.chromaFormat&&null!=this.sarNum&&null!=this.sarDen;return null!=this.mimeType&&null!=this.duration&&null!=this.metadata&&null!=this.hasKeyframesIndex&&e&&t}},{key:"isSeekable",value:function(){return!0===this.hasKeyframesIndex}},{key:"getNearestKeyframe",value:function(e){if(null==this.keyframesIndex)return null;var t=this.keyframesIndex,n=this._search(t.times,e);return{index:n,milliseconds:t.times[n],fileposition:t.filepositions[n]}}},{key:"_search",value:function(e,t){var n=0,i=e.length-1,r=0,s=0,a=i;for(t<e[0]&&(n=0,s=a+1);s<=a;){if((r=s+Math.floor((a-s)/2))===i||t>=e[r]&&t<e[r+1]){n=r;break}e[r]<t?s=r+1:a=r-1}return n}}]),e}();n.default=s},{}],8:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();n.SampleInfo=function e(t,n,r,s,a){i(this,e),this.dts=t,this.pts=n,this.duration=r,this.originalDts=s,this.isSyncPoint=a,this.fileposition=null},n.MediaSegmentInfo=function(){function e(){i(this,e),this.beginDts=0,this.endDts=0,this.beginPts=0,this.endPts=0,this.originalBeginDts=0,this.originalEndDts=0,this.syncPoints=[],this.firstSample=null,this.lastSample=null}return r(e,[{key:"appendSyncPoint",value:function(e){e.isSyncPoint=!0,this.syncPoints.push(e)}}]),e}(),n.IDRSampleList=function(){function e(){i(this,e),this._list=[]}return r(e,[{key:"clear",value:function(){this._list=[]}},{key:"appendArray",value:function(e){var t=this._list;0!==e.length&&(t.length>0&&e[0].originalDts<t[t.length-1].originalDts&&this.clear(),Array.prototype.push.apply(t,e))}},{key:"getLastSyncPointBeforeDts",value:function(e){if(0==this._list.length)return null;var t=this._list,n=0,i=t.length-1,r=0,s=0,a=i;for(e<t[0].dts&&(n=0,s=a+1);s<=a;){if((r=s+Math.floor((a-s)/2))===i||e>=t[r].dts&&e<t[r+1].dts){n=r;break}t[r].dts<e?s=r+1:a=r-1}return this._list[n]}}]),e}(),n.MediaSegmentInfoList=function(){function e(t){i(this,e),this._type=t,this._list=[],this._lastAppendLocation=-1}return r(e,[{key:"isEmpty",value:function(){return 0===this._list.length}},{key:"clear",value:function(){this._list=[],this._lastAppendLocation=-1}},{key:"_searchNearestSegmentBefore",value:function(e){var t=this._list;if(0===t.length)return-2;var n=t.length-1,i=0,r=0,s=n,a=0;if(e<t[0].originalBeginDts)return a=-1;for(;r<=s;){if((i=r+Math.floor((s-r)/2))===n||e>t[i].lastSample.originalDts&&e<t[i+1].originalBeginDts){a=i;break}t[i].originalBeginDts<e?r=i+1:s=i-1}return a}},{key:"_searchNearestSegmentAfter",value:function(e){return this._searchNearestSegmentBefore(e)+1}},{key:"append",value:function(e){var t=this._list,n=e,i=this._lastAppendLocation,r=0;-1!==i&&i<t.length&&n.originalBeginDts>=t[i].lastSample.originalDts&&(i===t.length-1||i<t.length-1&&n.originalBeginDts<t[i+1].originalBeginDts)?r=i+1:t.length>0&&(r=this._searchNearestSegmentBefore(n.originalBeginDts)+1),this._lastAppendLocation=r,this._list.splice(r,0,n)}},{key:"getLastSegmentBefore",value:function(e){var t=this._searchNearestSegmentBefore(e);return t>=0?this._list[t]:null}},{key:"getLastSampleBefore",value:function(e){var t=this.getLastSegmentBefore(e);return null!=t?t.lastSample:null}},{key:"getLastSyncPointBefore",value:function(e){for(var t=this._searchNearestSegmentBefore(e),n=this._list[t].syncPoints;0===n.length&&t>0;)t--,n=this._list[t].syncPoints;return n.length>0?n[n.length-1]:null}},{key:"type",get:function(){return this._type}},{key:"length",get:function(){return this._list.length}}]),e}()},{}],9:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("events"),o=i(a),u=e("../utils/logger.js"),l=i(u),d=e("../utils/browser.js"),h=i(d),f=e("./mse-events.js"),c=i(f),_=e("./media-segment-info.js"),m=e("../utils/exception.js"),p=function(){function e(t){r(this,e),this.TAG="MSEController",this._config=t,this._emitter=new o.default,this._config.isLive&&void 0==this._config.autoCleanupSourceBuffer&&(this._config.autoCleanupSourceBuffer=!0),this.e={onSourceOpen:this._onSourceOpen.bind(this),onSourceEnded:this._onSourceEnded.bind(this),onSourceClose:this._onSourceClose.bind(this),onSourceBufferError:this._onSourceBufferError.bind(this),onSourceBufferUpdateEnd:this._onSourceBufferUpdateEnd.bind(this)},this._mediaSource=null,this._mediaSourceObjectURL=null,this._mediaElement=null,this._isBufferFull=!1,this._hasPendingEos=!1,this._requireSetMediaDuration=!1,this._pendingMediaDuration=0,this._pendingSourceBufferInit=[],this._mimeTypes={video:null,audio:null},this._sourceBuffers={video:null,audio:null},this._lastInitSegments={video:null,audio:null},this._pendingSegments={video:[],audio:[]},this._pendingRemoveRanges={video:[],audio:[]},this._idrList=new _.IDRSampleList}return s(e,[{key:"destroy",value:function(){(this._mediaElement||this._mediaSource)&&this.detachMediaElement(),this.e=null,this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{key:"attachMediaElement",value:function(e){if(this._mediaSource)throw new m.IllegalStateException("MediaSource has been attached to an HTMLMediaElement!");var t=this._mediaSource=new window.MediaSource;t.addEventListener("sourceopen",this.e.onSourceOpen),t.addEventListener("sourceended",this.e.onSourceEnded),t.addEventListener("sourceclose",this.e.onSourceClose),this._mediaElement=e,this._mediaSourceObjectURL=window.URL.createObjectURL(this._mediaSource),e.src=this._mediaSourceObjectURL}},{key:"detachMediaElement",value:function(){if(this._mediaSource){var e=this._mediaSource;for(var t in this._sourceBuffers){var n=this._pendingSegments[t];n.splice(0,n.length),this._pendingSegments[t]=null,this._pendingRemoveRanges[t]=null,this._lastInitSegments[t]=null;var i=this._sourceBuffers[t];if(i){if("closed"!==e.readyState){try{e.removeSourceBuffer(i)}catch(e){l.default.e(this.TAG,e.message)}i.removeEventListener("error",this.e.onSourceBufferError),i.removeEventListener("updateend",this.e.onSourceBufferUpdateEnd)}this._mimeTypes[t]=null,this._sourceBuffers[t]=null}}if("open"===e.readyState)try{e.endOfStream()}catch(e){l.default.e(this.TAG,e.message)}e.removeEventListener("sourceopen",this.e.onSourceOpen),e.removeEventListener("sourceended",this.e.onSourceEnded),e.removeEventListener("sourceclose",this.e.onSourceClose),this._pendingSourceBufferInit=[],this._isBufferFull=!1,this._idrList.clear(),this._mediaSource=null}this._mediaElement&&(this._mediaElement.src="",this._mediaElement.removeAttribute("src"),this._mediaElement=null),this._mediaSourceObjectURL&&(window.URL.revokeObjectURL(this._mediaSourceObjectURL),this._mediaSourceObjectURL=null)}},{key:"appendInitSegment",value:function(e,t){if(!this._mediaSource||"open"!==this._mediaSource.readyState)return this._pendingSourceBufferInit.push(e),void this._pendingSegments[e.type].push(e);var n=e,i=""+n.container;n.codec&&n.codec.length>0&&(i+=";codecs="+n.codec);var r=!1;if(l.default.v(this.TAG,"Received Initialization Segment, mimeType: "+i),this._lastInitSegments[n.type]=n,i!==this._mimeTypes[n.type]){if(this._mimeTypes[n.type])l.default.v(this.TAG,"Notice: "+n.type+" mimeType changed, origin: "+this._mimeTypes[n.type]+", target: "+i);else{r=!0;try{var s=this._sourceBuffers[n.type]=this._mediaSource.addSourceBuffer(i);s.addEventListener("error",this.e.onSourceBufferError),s.addEventListener("updateend",this.e.onSourceBufferUpdateEnd)}catch(e){return l.default.e(this.TAG,e.message),void this._emitter.emit(c.default.ERROR,{code:e.code,msg:e.message})}}this._mimeTypes[n.type]=i}t||this._pendingSegments[n.type].push(n),r||this._sourceBuffers[n.type]&&!this._sourceBuffers[n.type].updating&&this._doAppendSegments(),h.default.safari&&"audio/mpeg"===n.container&&n.mediaDuration>0&&(this._requireSetMediaDuration=!0,this._pendingMediaDuration=n.mediaDuration/1e3,this._updateMediaSourceDuration())}},{key:"appendMediaSegment",value:function(e){var t=e;this._pendingSegments[t.type].push(t),this._config.autoCleanupSourceBuffer&&this._needCleanupSourceBuffer()&&this._doCleanupSourceBuffer();var n=this._sourceBuffers[t.type];!n||n.updating||this._hasPendingRemoveRanges()||this._doAppendSegments()}},{key:"seek",value:function(e){for(var t in this._sourceBuffers)if(this._sourceBuffers[t]){var n=this._sourceBuffers[t];if("open"===this._mediaSource.readyState)try{n.abort()}catch(e){l.default.e(this.TAG,e.message)}this._idrList.clear();var i=this._pendingSegments[t];if(i.splice(0,i.length),"closed"!==this._mediaSource.readyState){for(var r=0;r<n.buffered.length;r++){var s=n.buffered.start(r),a=n.buffered.end(r);this._pendingRemoveRanges[t].push({start:s,end:a})}if(n.updating||this._doRemoveRanges(),h.default.safari){var o=this._lastInitSegments[t];o&&(this._pendingSegments[t].push(o),n.updating||this._doAppendSegments())}}}}},{key:"endOfStream",value:function(){var e=this._mediaSource,t=this._sourceBuffers;if(!e||"open"!==e.readyState)return void(e&&"closed"===e.readyState&&this._hasPendingSegments()&&(this._hasPendingEos=!0));t.video&&t.video.updating||t.audio&&t.audio.updating?this._hasPendingEos=!0:(this._hasPendingEos=!1,e.endOfStream())}},{key:"getNearestKeyframe",value:function(e){return this._idrList.getLastSyncPointBeforeDts(e)}},{key:"_needCleanupSourceBuffer",value:function(){if(!this._config.autoCleanupSourceBuffer)return!1;var e=this._mediaElement.currentTime;for(var t in this._sourceBuffers){var n=this._sourceBuffers[t];if(n){var i=n.buffered;if(i.length>=1&&e-i.start(0)>=this._config.autoCleanupMaxBackwardDuration)return!0}}return!1}},{key:"_doCleanupSourceBuffer",value:function(){var e=this._mediaElement.currentTime;for(var t in this._sourceBuffers){var n=this._sourceBuffers[t];if(n){for(var i=n.buffered,r=!1,s=0;s<i.length;s++){var a=i.start(s),o=i.end(s);if(a<=e&&e<o+3){if(e-a>=this._config.autoCleanupMaxBackwardDuration){r=!0;var u=e-this._config.autoCleanupMinBackwardDuration;this._pendingRemoveRanges[t].push({start:a,end:u})}}else o<e&&(r=!0,this._pendingRemoveRanges[t].push({start:a,end:o}))}r&&!n.updating&&this._doRemoveRanges()}}}},{key:"_updateMediaSourceDuration",value:function(){var e=this._sourceBuffers;if(0!==this._mediaElement.readyState&&"open"===this._mediaSource.readyState&&!(e.video&&e.video.updating||e.audio&&e.audio.updating)){var t=this._mediaSource.duration,n=this._pendingMediaDuration;n>0&&(isNaN(t)||n>t)&&(l.default.v(this.TAG,"Update MediaSource duration from "+t+" to "+n),this._mediaSource.duration=n),this._requireSetMediaDuration=!1,this._pendingMediaDuration=0}}},{key:"_doRemoveRanges",value:function(){for(var e in this._pendingRemoveRanges)if(this._sourceBuffers[e]&&!this._sourceBuffers[e].updating)for(var t=this._sourceBuffers[e],n=this._pendingRemoveRanges[e];n.length&&!t.updating;){var i=n.shift();t.remove(i.start,i.end)}}},{key:"_doAppendSegments",value:function(){var e=this._pendingSegments;for(var t in e)if(this._sourceBuffers[t]&&!this._sourceBuffers[t].updating&&e[t].length>0){var n=e[t].shift();if(n.timestampOffset){var i=this._sourceBuffers[t].timestampOffset,r=n.timestampOffset/1e3,s=Math.abs(i-r);s>.1&&(l.default.v(this.TAG,"Update MPEG audio timestampOffset from "+i+" to "+r),this._sourceBuffers[t].timestampOffset=r),delete n.timestampOffset}if(!n.data||0===n.data.byteLength)continue;try{this._sourceBuffers[t].appendBuffer(n.data),this._isBufferFull=!1,"video"===t&&n.hasOwnProperty("info")&&this._idrList.appendArray(n.info.syncPoints)}catch(e){this._pendingSegments[t].unshift(n),22===e.code?(this._isBufferFull||this._emitter.emit(c.default.BUFFER_FULL),this._isBufferFull=!0):(l.default.e(this.TAG,e.message),this._emitter.emit(c.default.ERROR,{code:e.code,msg:e.message}))}}}},{key:"_onSourceOpen",value:function(){if(l.default.v(this.TAG,"MediaSource onSourceOpen"),this._mediaSource.removeEventListener("sourceopen",this.e.onSourceOpen),this._pendingSourceBufferInit.length>0)for(var e=this._pendingSourceBufferInit;e.length;){var t=e.shift();this.appendInitSegment(t,!0)}this._hasPendingSegments()&&this._doAppendSegments(),this._emitter.emit(c.default.SOURCE_OPEN)}},{key:"_onSourceEnded",value:function(){l.default.v(this.TAG,"MediaSource onSourceEnded")}},{key:"_onSourceClose",value:function(){l.default.v(this.TAG,"MediaSource onSourceClose"),this._mediaSource&&null!=this.e&&(this._mediaSource.removeEventListener("sourceopen",this.e.onSourceOpen),this._mediaSource.removeEventListener("sourceended",this.e.onSourceEnded),this._mediaSource.removeEventListener("sourceclose",this.e.onSourceClose))}},{key:"_hasPendingSegments",value:function(){var e=this._pendingSegments;return e.video.length>0||e.audio.length>0}},{key:"_hasPendingRemoveRanges",value:function(){var e=this._pendingRemoveRanges;return e.video.length>0||e.audio.length>0}},{key:"_onSourceBufferUpdateEnd",value:function(){this._requireSetMediaDuration?this._updateMediaSourceDuration():this._hasPendingRemoveRanges()?this._doRemoveRanges():this._hasPendingSegments()?this._doAppendSegments():this._hasPendingEos&&this.endOfStream(),this._emitter.emit(c.default.UPDATE_END)}},{key:"_onSourceBufferError",value:function(e){l.default.e(this.TAG,"SourceBuffer Error: "+e)}}]),e}();n.default=p},{"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./media-segment-info.js":8,"./mse-events.js":10,events:2}],10:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={ERROR:"error",SOURCE_OPEN:"source_open",UPDATE_END:"update_end",BUFFER_FULL:"buffer_full"};n.default=i},{}],11:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){ | |
| 2 | +function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("events"),o=i(a),u=e("../utils/logger.js"),l=i(u),d=e("../utils/logging-control.js"),h=i(d),f=e("./transmuxing-controller.js"),c=i(f),_=e("./transmuxing-events.js"),m=i(_),p=e("./transmuxing-worker.js"),v=i(p),g=e("./media-info.js"),y=i(g),E=function(){function t(n,i){if(r(this,t),this.TAG="Transmuxer",this._emitter=new o.default,i.enableWorker&&"undefined"!=typeof Worker)try{var s=e("webworkify");this._worker=s(v.default),this._workerDestroying=!1,this._worker.addEventListener("message",this._onWorkerMessage.bind(this)),this._worker.postMessage({cmd:"init",param:[n,i]}),this.e={onLoggingConfigChanged:this._onLoggingConfigChanged.bind(this)},h.default.registerListener(this.e.onLoggingConfigChanged),this._worker.postMessage({cmd:"logging_config",param:h.default.getConfig()})}catch(e){l.default.e(this.TAG,"Error while initialize transmuxing worker, fallback to inline transmuxing"),this._worker=null,this._controller=new c.default(n,i)}else this._controller=new c.default(n,i);if(this._controller){var a=this._controller;a.on(m.default.IO_ERROR,this._onIOError.bind(this)),a.on(m.default.DEMUX_ERROR,this._onDemuxError.bind(this)),a.on(m.default.INIT_SEGMENT,this._onInitSegment.bind(this)),a.on(m.default.MEDIA_SEGMENT,this._onMediaSegment.bind(this)),a.on(m.default.LOADING_COMPLETE,this._onLoadingComplete.bind(this)),a.on(m.default.RECOVERED_EARLY_EOF,this._onRecoveredEarlyEof.bind(this)),a.on(m.default.MEDIA_INFO,this._onMediaInfo.bind(this)),a.on(m.default.METADATA_ARRIVED,this._onMetaDataArrived.bind(this)),a.on(m.default.SCRIPTDATA_ARRIVED,this._onScriptDataArrived.bind(this)),a.on(m.default.STATISTICS_INFO,this._onStatisticsInfo.bind(this)),a.on(m.default.RECOMMEND_SEEKPOINT,this._onRecommendSeekpoint.bind(this))}}return s(t,[{key:"destroy",value:function(){this._worker?this._workerDestroying||(this._workerDestroying=!0,this._worker.postMessage({cmd:"destroy"}),h.default.removeListener(this.e.onLoggingConfigChanged),this.e=null):(this._controller.destroy(),this._controller=null),this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{key:"hasWorker",value:function(){return null!=this._worker}},{key:"open",value:function(){this._worker?this._worker.postMessage({cmd:"start"}):this._controller.start()}},{key:"close",value:function(){this._worker?this._worker.postMessage({cmd:"stop"}):this._controller.stop()}},{key:"seek",value:function(e){this._worker?this._worker.postMessage({cmd:"seek",param:e}):this._controller.seek(e)}},{key:"pause",value:function(){this._worker?this._worker.postMessage({cmd:"pause"}):this._controller.pause()}},{key:"resume",value:function(){this._worker?this._worker.postMessage({cmd:"resume"}):this._controller.resume()}},{key:"_onInitSegment",value:function(e,t){var n=this;Promise.resolve().then(function(){n._emitter.emit(m.default.INIT_SEGMENT,e,t)})}},{key:"_onMediaSegment",value:function(e,t){var n=this;Promise.resolve().then(function(){n._emitter.emit(m.default.MEDIA_SEGMENT,e,t)})}},{key:"_onLoadingComplete",value:function(){var e=this;Promise.resolve().then(function(){e._emitter.emit(m.default.LOADING_COMPLETE)})}},{key:"_onRecoveredEarlyEof",value:function(){var e=this;Promise.resolve().then(function(){e._emitter.emit(m.default.RECOVERED_EARLY_EOF)})}},{key:"_onMediaInfo",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.MEDIA_INFO,e)})}},{key:"_onMetaDataArrived",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.METADATA_ARRIVED,e)})}},{key:"_onScriptDataArrived",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.SCRIPTDATA_ARRIVED,e)})}},{key:"_onStatisticsInfo",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.STATISTICS_INFO,e)})}},{key:"_onIOError",value:function(e,t){var n=this;Promise.resolve().then(function(){n._emitter.emit(m.default.IO_ERROR,e,t)})}},{key:"_onDemuxError",value:function(e,t){var n=this;Promise.resolve().then(function(){n._emitter.emit(m.default.DEMUX_ERROR,e,t)})}},{key:"_onRecommendSeekpoint",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.RECOMMEND_SEEKPOINT,e)})}},{key:"_onLoggingConfigChanged",value:function(e){this._worker&&this._worker.postMessage({cmd:"logging_config",param:e})}},{key:"_onWorkerMessage",value:function(e){var t=e.data,n=t.data;if("destroyed"===t.msg||this._workerDestroying)return this._workerDestroying=!1,this._worker.terminate(),void(this._worker=null);switch(t.msg){case m.default.INIT_SEGMENT:case m.default.MEDIA_SEGMENT:this._emitter.emit(t.msg,n.type,n.data);break;case m.default.LOADING_COMPLETE:case m.default.RECOVERED_EARLY_EOF:this._emitter.emit(t.msg);break;case m.default.MEDIA_INFO:Object.setPrototypeOf(n,y.default.prototype),this._emitter.emit(t.msg,n);break;case m.default.METADATA_ARRIVED:case m.default.SCRIPTDATA_ARRIVED:case m.default.STATISTICS_INFO:this._emitter.emit(t.msg,n);break;case m.default.IO_ERROR:case m.default.DEMUX_ERROR:this._emitter.emit(t.msg,n.type,n.info);break;case m.default.RECOMMEND_SEEKPOINT:this._emitter.emit(t.msg,n);break;case"logcat_callback":l.default.emitter.emit("log",n.type,n.logcat)}}}]),t}();n.default=E},{"../utils/logger.js":41,"../utils/logging-control.js":42,"./media-info.js":7,"./transmuxing-controller.js":12,"./transmuxing-events.js":13,"./transmuxing-worker.js":14,events:2,webworkify:4}],12:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("events"),o=i(a),u=e("../utils/logger.js"),l=i(u),d=e("../utils/browser.js"),h=i(d),f=e("./media-info.js"),c=i(f),_=e("../demux/flv-demuxer.js"),m=i(_),p=e("../remux/mp4-remuxer.js"),v=i(p),g=e("../demux/demux-errors.js"),y=i(g),E=e("../io/io-controller.js"),b=i(E),S=e("./transmuxing-events.js"),k=i(S),L=(e("../io/loader.js"),function(){function e(t,n){r(this,e),this.TAG="TransmuxingController",this._emitter=new o.default,this._config=n,t.segments||(t.segments=[{duration:t.duration,filesize:t.filesize,url:t.url}]),"boolean"!=typeof t.cors&&(t.cors=!0),"boolean"!=typeof t.withCredentials&&(t.withCredentials=!1),this._mediaDataSource=t,this._currentSegmentIndex=0;var i=0;this._mediaDataSource.segments.forEach(function(e){e.timestampBase=i,i+=e.duration,e.cors=t.cors,e.withCredentials=t.withCredentials,n.referrerPolicy&&(e.referrerPolicy=n.referrerPolicy)}),isNaN(i)||this._mediaDataSource.duration===i||(this._mediaDataSource.duration=i),this._mediaInfo=null,this._demuxer=null,this._remuxer=null,this._ioctl=null,this._pendingSeekTime=null,this._pendingResolveSeekPoint=null,this._statisticsReporter=null}return s(e,[{key:"destroy",value:function(){this._mediaInfo=null,this._mediaDataSource=null,this._statisticsReporter&&this._disableStatisticsReporter(),this._ioctl&&(this._ioctl.destroy(),this._ioctl=null),this._demuxer&&(this._demuxer.destroy(),this._demuxer=null),this._remuxer&&(this._remuxer.destroy(),this._remuxer=null),this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{key:"start",value:function(){this._loadSegment(0),this._enableStatisticsReporter()}},{key:"_loadSegment",value:function(e,t){this._currentSegmentIndex=e;var n=this._mediaDataSource.segments[e],i=this._ioctl=new b.default(n,this._config,e);i.onError=this._onIOException.bind(this),i.onSeeked=this._onIOSeeked.bind(this),i.onComplete=this._onIOComplete.bind(this),i.onRedirect=this._onIORedirect.bind(this),i.onRecoveredEarlyEof=this._onIORecoveredEarlyEof.bind(this),t?this._demuxer.bindDataSource(this._ioctl):i.onDataArrival=this._onInitChunkArrival.bind(this),i.open(t)}},{key:"stop",value:function(){this._internalAbort(),this._disableStatisticsReporter()}},{key:"_internalAbort",value:function(){this._ioctl&&(this._ioctl.destroy(),this._ioctl=null)}},{key:"pause",value:function(){this._ioctl&&this._ioctl.isWorking()&&(this._ioctl.pause(),this._disableStatisticsReporter())}},{key:"resume",value:function(){this._ioctl&&this._ioctl.isPaused()&&(this._ioctl.resume(),this._enableStatisticsReporter())}},{key:"seek",value:function(e){if(null!=this._mediaInfo&&this._mediaInfo.isSeekable()){var t=this._searchSegmentIndexContains(e);if(t===this._currentSegmentIndex){var n=this._mediaInfo.segments[t];if(void 0==n)this._pendingSeekTime=e;else{var i=n.getNearestKeyframe(e);this._remuxer.seek(i.milliseconds),this._ioctl.seek(i.fileposition),this._pendingResolveSeekPoint=i.milliseconds}}else{var r=this._mediaInfo.segments[t];if(void 0==r)this._pendingSeekTime=e,this._internalAbort(),this._remuxer.seek(),this._remuxer.insertDiscontinuity(),this._loadSegment(t);else{var s=r.getNearestKeyframe(e);this._internalAbort(),this._remuxer.seek(e),this._remuxer.insertDiscontinuity(),this._demuxer.resetMediaInfo(),this._demuxer.timestampBase=this._mediaDataSource.segments[t].timestampBase,this._loadSegment(t,s.fileposition),this._pendingResolveSeekPoint=s.milliseconds,this._reportSegmentMediaInfo(t)}}this._enableStatisticsReporter()}}},{key:"_searchSegmentIndexContains",value:function(e){for(var t=this._mediaDataSource.segments,n=t.length-1,i=0;i<t.length;i++)if(e<t[i].timestampBase){n=i-1;break}return n}},{key:"_onInitChunkArrival",value:function(e,t){var n=this,i=null,r=0;if(t>0)this._demuxer.bindDataSource(this._ioctl),this._demuxer.timestampBase=this._mediaDataSource.segments[this._currentSegmentIndex].timestampBase,r=this._demuxer.parseChunks(e,t);else if((i=m.default.probe(e)).match){this._demuxer=new m.default(i,this._config),this._remuxer||(this._remuxer=new v.default(this._config));var s=this._mediaDataSource;void 0==s.duration||isNaN(s.duration)||(this._demuxer.overridedDuration=s.duration),"boolean"==typeof s.hasAudio&&(this._demuxer.overridedHasAudio=s.hasAudio),"boolean"==typeof s.hasVideo&&(this._demuxer.overridedHasVideo=s.hasVideo),this._demuxer.timestampBase=s.segments[this._currentSegmentIndex].timestampBase,this._demuxer.onError=this._onDemuxException.bind(this),this._demuxer.onMediaInfo=this._onMediaInfo.bind(this),this._demuxer.onMetaDataArrived=this._onMetaDataArrived.bind(this),this._demuxer.onScriptDataArrived=this._onScriptDataArrived.bind(this),this._remuxer.bindDataSource(this._demuxer.bindDataSource(this._ioctl)),this._remuxer.onInitSegment=this._onRemuxerInitSegmentArrival.bind(this),this._remuxer.onMediaSegment=this._onRemuxerMediaSegmentArrival.bind(this),r=this._demuxer.parseChunks(e,t)}else i=null,l.default.e(this.TAG,"Non-FLV, Unsupported media type!"),Promise.resolve().then(function(){n._internalAbort()}),this._emitter.emit(k.default.DEMUX_ERROR,y.default.FORMAT_UNSUPPORTED,"Non-FLV, Unsupported media type"),r=0;return r}},{key:"_onMediaInfo",value:function(e){var t=this;null==this._mediaInfo&&(this._mediaInfo=Object.assign({},e),this._mediaInfo.keyframesIndex=null,this._mediaInfo.segments=[],this._mediaInfo.segmentCount=this._mediaDataSource.segments.length,Object.setPrototypeOf(this._mediaInfo,c.default.prototype));var n=Object.assign({},e);Object.setPrototypeOf(n,c.default.prototype),this._mediaInfo.segments[this._currentSegmentIndex]=n,this._reportSegmentMediaInfo(this._currentSegmentIndex),null!=this._pendingSeekTime&&Promise.resolve().then(function(){var e=t._pendingSeekTime;t._pendingSeekTime=null,t.seek(e)})}},{key:"_onMetaDataArrived",value:function(e){this._emitter.emit(k.default.METADATA_ARRIVED,e)}},{key:"_onScriptDataArrived",value:function(e){this._emitter.emit(k.default.SCRIPTDATA_ARRIVED,e)}},{key:"_onIOSeeked",value:function(){this._remuxer.insertDiscontinuity()}},{key:"_onIOComplete",value:function(e){var t=e,n=t+1;n<this._mediaDataSource.segments.length?(this._internalAbort(),this._remuxer.flushStashedSamples(),this._loadSegment(n)):(this._remuxer.flushStashedSamples(),this._emitter.emit(k.default.LOADING_COMPLETE),this._disableStatisticsReporter())}},{key:"_onIORedirect",value:function(e){var t=this._ioctl.extraData;this._mediaDataSource.segments[t].redirectedURL=e}},{key:"_onIORecoveredEarlyEof",value:function(){this._emitter.emit(k.default.RECOVERED_EARLY_EOF)}},{key:"_onIOException",value:function(e,t){l.default.e(this.TAG,"IOException: type = "+e+", code = "+t.code+", msg = "+t.msg),this._emitter.emit(k.default.IO_ERROR,e,t),this._disableStatisticsReporter()}},{key:"_onDemuxException",value:function(e,t){l.default.e(this.TAG,"DemuxException: type = "+e+", info = "+t),this._emitter.emit(k.default.DEMUX_ERROR,e,t)}},{key:"_onRemuxerInitSegmentArrival",value:function(e,t){this._emitter.emit(k.default.INIT_SEGMENT,e,t)}},{key:"_onRemuxerMediaSegmentArrival",value:function(e,t){if(null==this._pendingSeekTime&&(this._emitter.emit(k.default.MEDIA_SEGMENT,e,t),null!=this._pendingResolveSeekPoint&&"video"===e)){var n=t.info.syncPoints,i=this._pendingResolveSeekPoint;this._pendingResolveSeekPoint=null,h.default.safari&&n.length>0&&n[0].originalDts===i&&(i=n[0].pts),this._emitter.emit(k.default.RECOMMEND_SEEKPOINT,i)}}},{key:"_enableStatisticsReporter",value:function(){null==this._statisticsReporter&&(this._statisticsReporter=self.setInterval(this._reportStatisticsInfo.bind(this),this._config.statisticsInfoReportInterval))}},{key:"_disableStatisticsReporter",value:function(){this._statisticsReporter&&(self.clearInterval(this._statisticsReporter),this._statisticsReporter=null)}},{key:"_reportSegmentMediaInfo",value:function(e){var t=this._mediaInfo.segments[e],n=Object.assign({},t);n.duration=this._mediaInfo.duration,n.segmentCount=this._mediaInfo.segmentCount,delete n.segments,delete n.keyframesIndex,this._emitter.emit(k.default.MEDIA_INFO,n)}},{key:"_reportStatisticsInfo",value:function(){var e={};e.url=this._ioctl.currentURL,e.hasRedirect=this._ioctl.hasRedirect,e.hasRedirect&&(e.redirectedURL=this._ioctl.currentRedirectedURL),e.speed=this._ioctl.currentSpeed,e.loaderType=this._ioctl.loaderType,e.currentSegmentIndex=this._currentSegmentIndex,e.totalSegmentCount=this._mediaDataSource.segments.length,this._emitter.emit(k.default.STATISTICS_INFO,e)}}]),e}());n.default=L},{"../demux/demux-errors.js":16,"../demux/flv-demuxer.js":18,"../io/io-controller.js":23,"../io/loader.js":24,"../remux/mp4-remuxer.js":38,"../utils/browser.js":39,"../utils/logger.js":41,"./media-info.js":7,"./transmuxing-events.js":13,events:2}],13:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={IO_ERROR:"io_error",DEMUX_ERROR:"demux_error",INIT_SEGMENT:"init_segment",MEDIA_SEGMENT:"media_segment",LOADING_COMPLETE:"loading_complete",RECOVERED_EARLY_EOF:"recovered_early_eof",MEDIA_INFO:"media_info",METADATA_ARRIVED:"metadata_arrived",SCRIPTDATA_ARRIVED:"scriptdata_arrived",STATISTICS_INFO:"statistics_info",RECOMMEND_SEEKPOINT:"recommend_seekpoint"};n.default=i},{}],14:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(n,"__esModule",{value:!0});var r=e("../utils/logger.js"),s=(i(r),e("../utils/logging-control.js")),a=i(s),o=e("../utils/polyfill.js"),u=i(o),l=e("./transmuxing-controller.js"),d=i(l),h=e("./transmuxing-events.js"),f=i(h),c=function(e){function t(t,n){var i={msg:f.default.INIT_SEGMENT,data:{type:t,data:n}};e.postMessage(i,[n.data])}function n(t,n){var i={msg:f.default.MEDIA_SEGMENT,data:{type:t,data:n}};e.postMessage(i,[n.data])}function i(){var t={msg:f.default.LOADING_COMPLETE};e.postMessage(t)}function r(){var t={msg:f.default.RECOVERED_EARLY_EOF};e.postMessage(t)}function s(t){var n={msg:f.default.MEDIA_INFO,data:t};e.postMessage(n)}function o(t){var n={msg:f.default.METADATA_ARRIVED,data:t};e.postMessage(n)}function l(t){var n={msg:f.default.SCRIPTDATA_ARRIVED,data:t};e.postMessage(n)}function h(t){var n={msg:f.default.STATISTICS_INFO,data:t};e.postMessage(n)}function c(t,n){e.postMessage({msg:f.default.IO_ERROR,data:{type:t,info:n}})}function _(t,n){e.postMessage({msg:f.default.DEMUX_ERROR,data:{type:t,info:n}})}function m(t){e.postMessage({msg:f.default.RECOMMEND_SEEKPOINT,data:t})}function p(t,n){e.postMessage({msg:"logcat_callback",data:{type:t,logcat:n}})}var v=null,g=p.bind(this);u.default.install(),e.addEventListener("message",function(u){switch(u.data.cmd){case"init":v=new d.default(u.data.param[0],u.data.param[1]),v.on(f.default.IO_ERROR,c.bind(this)),v.on(f.default.DEMUX_ERROR,_.bind(this)),v.on(f.default.INIT_SEGMENT,t.bind(this)),v.on(f.default.MEDIA_SEGMENT,n.bind(this)),v.on(f.default.LOADING_COMPLETE,i.bind(this)),v.on(f.default.RECOVERED_EARLY_EOF,r.bind(this)),v.on(f.default.MEDIA_INFO,s.bind(this)),v.on(f.default.METADATA_ARRIVED,o.bind(this)),v.on(f.default.SCRIPTDATA_ARRIVED,l.bind(this)),v.on(f.default.STATISTICS_INFO,h.bind(this)),v.on(f.default.RECOMMEND_SEEKPOINT,m.bind(this));break;case"destroy":v&&(v.destroy(),v=null),e.postMessage({msg:"destroyed"});break;case"start":v.start();break;case"stop":v.stop();break;case"seek":v.seek(u.data.param);break;case"pause":v.pause();break;case"resume":v.resume();break;case"logging_config":var p=u.data.param;a.default.applyConfig(p),!0===p.enableCallback?a.default.addLogListener(g):a.default.removeLogListener(g)}})};n.default=c},{"../utils/logger.js":41,"../utils/logging-control.js":42,"../utils/polyfill.js":43,"./transmuxing-controller.js":12,"./transmuxing-events.js":13}],15:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("../utils/logger.js"),o=i(a),u=e("../utils/utf8-conv.js"),l=i(u),d=e("../utils/exception.js"),h=function(){var e=new ArrayBuffer(2);return new DataView(e).setInt16(0,256,!0),256===new Int16Array(e)[0]}(),f=function(){function e(){r(this,e)}return s(e,null,[{key:"parseScriptData",value:function(t,n,i){var r={};try{var s=e.parseValue(t,n,i),a=e.parseValue(t,n+s.size,i-s.size);r[s.data]=a.data}catch(e){o.default.e("AMF",e.toString())}return r}},{key:"parseObject",value:function(t,n,i){if(i<3)throw new d.IllegalStateException("Data not enough when parse ScriptDataObject");var r=e.parseString(t,n,i),s=e.parseValue(t,n+r.size,i-r.size),a=s.objectEnd;return{data:{name:r.data,value:s.data},size:r.size+s.size,objectEnd:a}}},{key:"parseVariable",value:function(t,n,i){return e.parseObject(t,n,i)}},{key:"parseString",value:function(e,t,n){if(n<2)throw new d.IllegalStateException("Data not enough when parse String");var i=new DataView(e,t,n),r=i.getUint16(0,!h),s=void 0;return s=r>0?(0,l.default)(new Uint8Array(e,t+2,r)):"",{data:s,size:2+r}}},{key:"parseLongString",value:function(e,t,n){if(n<4)throw new d.IllegalStateException("Data not enough when parse LongString");var i=new DataView(e,t,n),r=i.getUint32(0,!h),s=void 0;return s=r>0?(0,l.default)(new Uint8Array(e,t+4,r)):"",{data:s,size:4+r}}},{key:"parseDate",value:function(e,t,n){if(n<10)throw new d.IllegalStateException("Data size invalid when parse Date");var i=new DataView(e,t,n),r=i.getFloat64(0,!h);return r+=60*i.getInt16(8,!h)*1e3,{data:new Date(r),size:10}}},{key:"parseValue",value:function(t,n,i){if(i<1)throw new d.IllegalStateException("Data not enough when parse Value");var r=new DataView(t,n,i),s=1,a=r.getUint8(0),u=void 0,l=!1;try{switch(a){case 0:u=r.getFloat64(1,!h),s+=8;break;case 1:u=!!r.getUint8(1),s+=1;break;case 2:var f=e.parseString(t,n+1,i-1);u=f.data,s+=f.size;break;case 3:u={};var c=0;for(9==(16777215&r.getUint32(i-4,!h))&&(c=3);s<i-4;){var _=e.parseObject(t,n+s,i-s-c);if(_.objectEnd)break;u[_.data.name]=_.data.value,s+=_.size}if(s<=i-3){9===(16777215&r.getUint32(s-1,!h))&&(s+=3)}break;case 8:u={},s+=4;var m=0;for(9==(16777215&r.getUint32(i-4,!h))&&(m=3);s<i-8;){var p=e.parseVariable(t,n+s,i-s-m);if(p.objectEnd)break;u[p.data.name]=p.data.value,s+=p.size}if(s<=i-3){9===(16777215&r.getUint32(s-1,!h))&&(s+=3)}break;case 9:u=void 0,s=1,l=!0;break;case 10:u=[];var v=r.getUint32(1,!h);s+=4;for(var g=0;g<v;g++){var y=e.parseValue(t,n+s,i-s);u.push(y.data),s+=y.size}break;case 11:var E=e.parseDate(t,n+1,i-1);u=E.data,s+=E.size;break;case 12:var b=e.parseString(t,n+1,i-1);u=b.data,s+=b.size;break;default:s=i,o.default.w("AMF","Unsupported AMF value type "+a)}}catch(e){o.default.e("AMF",e.toString())}return{data:u,size:s,objectEnd:l}}}]),e}();n.default=f},{"../utils/exception.js":40,"../utils/logger.js":41,"../utils/utf8-conv.js":44}],16:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={OK:"OK",FORMAT_ERROR:"FormatError",FORMAT_UNSUPPORTED:"FormatUnsupported",CODEC_UNSUPPORTED:"CodecUnsupported"};n.default=i},{}],17:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("../utils/exception.js"),a=function(){function e(t){i(this,e),this.TAG="ExpGolomb",this._buffer=t,this._buffer_index=0,this._total_bytes=t.byteLength,this._total_bits=8*t.byteLength,this._current_word=0,this._current_word_bits_left=0}return r(e,[{key:"destroy",value:function(){this._buffer=null}},{key:"_fillCurrentWord",value:function(){var e=this._total_bytes-this._buffer_index;if(e<=0)throw new s.IllegalStateException("ExpGolomb: _fillCurrentWord() but no bytes available");var t=Math.min(4,e),n=new Uint8Array(4);n.set(this._buffer.subarray(this._buffer_index,this._buffer_index+t)),this._current_word=new DataView(n.buffer).getUint32(0,!1),this._buffer_index+=t,this._current_word_bits_left=8*t}},{key:"readBits",value:function(e){if(e>32)throw new s.InvalidArgumentException("ExpGolomb: readBits() bits exceeded max 32bits!");if(e<=this._current_word_bits_left){var t=this._current_word>>>32-e;return this._current_word<<=e,this._current_word_bits_left-=e,t}var n=this._current_word_bits_left?this._current_word:0;n>>>=32-this._current_word_bits_left;var i=e-this._current_word_bits_left;this._fillCurrentWord();var r=Math.min(i,this._current_word_bits_left),a=this._current_word>>>32-r;return this._current_word<<=r,this._current_word_bits_left-=r,n=n<<r|a}},{key:"readBool",value:function(){return 1===this.readBits(1)}},{key:"readByte",value:function(){return this.readBits(8)}},{key:"_skipLeadingZero",value:function(){var e=void 0;for(e=0;e<this._current_word_bits_left;e++)if(0!=(this._current_word&2147483648>>>e))return this._current_word<<=e,this._current_word_bits_left-=e,e;return this._fillCurrentWord(),e+this._skipLeadingZero()}},{key:"readUEG",value:function(){var e=this._skipLeadingZero();return this.readBits(e+1)-1}},{key:"readSEG",value:function(){var e=this.readUEG();return 1&e?e+1>>>1:-1*(e>>>1)}}]),e}();n.default=a},{"../utils/exception.js":40}],18:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){return e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3]}Object.defineProperty(n,"__esModule",{value:!0});var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),u=e("../utils/logger.js"),l=i(u),d=e("./amf-parser.js"),h=i(d),f=e("./sps-parser.js"),c=i(f),_=e("./demux-errors.js"),m=i(_),p=e("../core/media-info.js"),v=i(p),g=e("../utils/exception.js"),y=function(){function e(t,n){r(this,e),this.TAG="FLVDemuxer",this._config=n,this._onError=null,this._onMediaInfo=null,this._onMetaDataArrived=null,this._onScriptDataArrived=null,this._onTrackMetadata=null,this._onDataAvailable=null,this._dataOffset=t.dataOffset,this._firstParse=!0,this._dispatch=!1,this._hasAudio=t.hasAudioTrack,this._hasVideo=t.hasVideoTrack,this._hasAudioFlagOverrided=!1,this._hasVideoFlagOverrided=!1,this._audioInitialMetadataDispatched=!1,this._videoInitialMetadataDispatched=!1,this._mediaInfo=new v.default,this._mediaInfo.hasAudio=this._hasAudio,this._mediaInfo.hasVideo=this._hasVideo,this._metadata=null,this._audioMetadata=null,this._videoMetadata=null,this._naluLengthSize=4,this._timestampBase=0,this._timescale=1e3,this._duration=0,this._durationOverrided=!1,this._referenceFrameRate={fixed:!0,fps:23.976,fps_num:23976,fps_den:1e3},this._flvSoundRateTable=[5500,11025,22050,44100,48e3],this._mpegSamplingRates=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],this._mpegAudioV10SampleRateTable=[44100,48e3,32e3,0],this._mpegAudioV20SampleRateTable=[22050,24e3,16e3,0],this._mpegAudioV25SampleRateTable=[11025,12e3,8e3,0],this._mpegAudioL1BitRateTable=[0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,-1],this._mpegAudioL2BitRateTable=[0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,-1],this._mpegAudioL3BitRateTable=[0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,-1],this._videoTrack={type:"video",id:1,sequenceNumber:0,samples:[],length:0},this._audioTrack={type:"audio",id:2,sequenceNumber:0,samples:[],length:0},this._littleEndian=function(){var e=new ArrayBuffer(2);return new DataView(e).setInt16(0,256,!0),256===new Int16Array(e)[0]}()}return o(e,[{key:"destroy",value:function(){this._mediaInfo=null,this._metadata=null,this._audioMetadata=null,this._videoMetadata=null,this._videoTrack=null,this._audioTrack=null,this._onError=null,this._onMediaInfo=null,this._onMetaDataArrived=null,this._onScriptDataArrived=null,this._onTrackMetadata=null,this._onDataAvailable=null}},{key:"bindDataSource",value:function(e){return e.onDataArrival=this.parseChunks.bind(this),this}},{key:"resetMediaInfo",value:function(){this._mediaInfo=new v.default}},{key:"_isInitialMetadataDispatched",value:function(){return this._hasAudio&&this._hasVideo?this._audioInitialMetadataDispatched&&this._videoInitialMetadataDispatched:this._hasAudio&&!this._hasVideo?this._audioInitialMetadataDispatched:!(this._hasAudio||!this._hasVideo)&&this._videoInitialMetadataDispatched}},{key:"parseChunks",value:function(t,n){if(!(this._onError&&this._onMediaInfo&&this._onTrackMetadata&&this._onDataAvailable))throw new g.IllegalStateException("Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified");var i=0,r=this._littleEndian;if(0===n){if(!(t.byteLength>13))return 0;i=e.probe(t).dataOffset}if(this._firstParse){this._firstParse=!1,n+i!==this._dataOffset&&l.default.w(this.TAG,"First time parsing but chunk byteStart invalid!");0!==new DataView(t,i).getUint32(0,!r)&&l.default.w(this.TAG,"PrevTagSize0 !== 0 !!!"),i+=4}for(;i<t.byteLength;){this._dispatch=!0;var s=new DataView(t,i);if(i+11+4>t.byteLength)break;var a=s.getUint8(0),o=16777215&s.getUint32(0,!r);if(i+11+o+4>t.byteLength)break;if(8===a||9===a||18===a){var u=s.getUint8(4),d=s.getUint8(5),h=s.getUint8(6),f=s.getUint8(7),c=h|d<<8|u<<16|f<<24;0!==(16777215&s.getUint32(7,!r))&&l.default.w(this.TAG,"Meet tag which has StreamID != 0!");var _=i+11;switch(a){case 8:this._parseAudioData(t,_,o,c);break;case 9:this._parseVideoData(t,_,o,c,n+i);break;case 18:this._parseScriptData(t,_,o)}var m=s.getUint32(11+o,!r);m!==11+o&&l.default.w(this.TAG,"Invalid PrevTagSize "+m),i+=11+o+4}else l.default.w(this.TAG,"Unsupported tag type "+a+", skipped"),i+=11+o+4}return this._isInitialMetadataDispatched()&&this._dispatch&&(this._audioTrack.length||this._videoTrack.length)&&this._onDataAvailable(this._audioTrack,this._videoTrack),i}},{key:"_parseScriptData",value:function(e,t,n){var i=h.default.parseScriptData(e,t,n);if(i.hasOwnProperty("onMetaData")){if(null==i.onMetaData||"object"!==a(i.onMetaData))return void l.default.w(this.TAG,"Invalid onMetaData structure!");this._metadata&&l.default.w(this.TAG,"Found another onMetaData tag!"),this._metadata=i;var r=this._metadata.onMetaData;if(this._onMetaDataArrived&&this._onMetaDataArrived(Object.assign({},r)),"boolean"==typeof r.hasAudio&&!1===this._hasAudioFlagOverrided&&(this._hasAudio=r.hasAudio,this._mediaInfo.hasAudio=this._hasAudio),"boolean"==typeof r.hasVideo&&!1===this._hasVideoFlagOverrided&&(this._hasVideo=r.hasVideo,this._mediaInfo.hasVideo=this._hasVideo),"number"==typeof r.audiodatarate&&(this._mediaInfo.audioDataRate=r.audiodatarate),"number"==typeof r.videodatarate&&(this._mediaInfo.videoDataRate=r.videodatarate),"number"==typeof r.width&&(this._mediaInfo.width=r.width),"number"==typeof r.height&&(this._mediaInfo.height=r.height),"number"==typeof r.duration){if(!this._durationOverrided){var s=Math.floor(r.duration*this._timescale);this._duration=s,this._mediaInfo.duration=s}}else this._mediaInfo.duration=0;if("number"==typeof r.framerate){var o=Math.floor(1e3*r.framerate);if(o>0){var u=o/1e3;this._referenceFrameRate.fixed=!0,this._referenceFrameRate.fps=u,this._referenceFrameRate.fps_num=o,this._referenceFrameRate.fps_den=1e3,this._mediaInfo.fps=u}}if("object"===a(r.keyframes)){this._mediaInfo.hasKeyframesIndex=!0;var d=r.keyframes;this._mediaInfo.keyframesIndex=this._parseKeyframesIndex(d),r.keyframes=null}else this._mediaInfo.hasKeyframesIndex=!1;this._dispatch=!1,this._mediaInfo.metadata=r,l.default.v(this.TAG,"Parsed onMetaData"),this._mediaInfo.isComplete()&&this._onMediaInfo(this._mediaInfo)}Object.keys(i).length>0&&this._onScriptDataArrived&&this._onScriptDataArrived(Object.assign({},i))}},{key:"_parseKeyframesIndex",value:function(e){for(var t=[],n=[],i=1;i<e.times.length;i++){var r=this._timestampBase+Math.floor(1e3*e.times[i]);t.push(r),n.push(e.filepositions[i])}return{times:t,filepositions:n}}},{key:"_parseAudioData",value:function(e,t,n,i){if(n<=1)return void l.default.w(this.TAG,"Flv: Invalid audio packet, missing SoundData payload!");if(!0!==this._hasAudioFlagOverrided||!1!==this._hasAudio){var r=(this._littleEndian,new DataView(e,t,n)),s=r.getUint8(0),a=s>>>4;if(2!==a&&10!==a)return void this._onError(m.default.CODEC_UNSUPPORTED,"Flv: Unsupported audio codec idx: "+a);var o=0,u=(12&s)>>>2;if(!(u>=0&&u<=4))return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid audio sample rate idx: "+u);o=this._flvSoundRateTable[u];var d=1&s,h=this._audioMetadata,f=this._audioTrack;if(h||(!1===this._hasAudio&&!1===this._hasAudioFlagOverrided&&(this._hasAudio=!0,this._mediaInfo.hasAudio=!0),h=this._audioMetadata={},h.type="audio",h.id=f.id,h.timescale=this._timescale,h.duration=this._duration,h.audioSampleRate=o,h.channelCount=0===d?1:2),10===a){var c=this._parseAACAudioData(e,t+1,n-1);if(void 0==c)return;if(0===c.packetType){h.config&&l.default.w(this.TAG,"Found another AudioSpecificConfig!");var _=c.data;h.audioSampleRate=_.samplingRate,h.channelCount=_.channelCount,h.codec=_.codec,h.originalCodec=_.originalCodec,h.config=_.config, | |
| 3 | +h.refSampleDuration=1024/h.audioSampleRate*h.timescale,l.default.v(this.TAG,"Parsed AudioSpecificConfig"),this._isInitialMetadataDispatched()?this._dispatch&&(this._audioTrack.length||this._videoTrack.length)&&this._onDataAvailable(this._audioTrack,this._videoTrack):this._audioInitialMetadataDispatched=!0,this._dispatch=!1,this._onTrackMetadata("audio",h);var p=this._mediaInfo;p.audioCodec=h.originalCodec,p.audioSampleRate=h.audioSampleRate,p.audioChannelCount=h.channelCount,p.hasVideo?null!=p.videoCodec&&(p.mimeType='video/x-flv; codecs="'+p.videoCodec+","+p.audioCodec+'"'):p.mimeType='video/x-flv; codecs="'+p.audioCodec+'"',p.isComplete()&&this._onMediaInfo(p)}else if(1===c.packetType){var v=this._timestampBase+i,g={unit:c.data,length:c.data.byteLength,dts:v,pts:v};f.samples.push(g),f.length+=c.data.length}else l.default.e(this.TAG,"Flv: Unsupported AAC data type "+c.packetType)}else if(2===a){if(!h.codec){var y=this._parseMP3AudioData(e,t+1,n-1,!0);if(void 0==y)return;h.audioSampleRate=y.samplingRate,h.channelCount=y.channelCount,h.codec=y.codec,h.originalCodec=y.originalCodec,h.refSampleDuration=1152/h.audioSampleRate*h.timescale,l.default.v(this.TAG,"Parsed MPEG Audio Frame Header"),this._audioInitialMetadataDispatched=!0,this._onTrackMetadata("audio",h);var E=this._mediaInfo;E.audioCodec=h.codec,E.audioSampleRate=h.audioSampleRate,E.audioChannelCount=h.channelCount,E.audioDataRate=y.bitRate,E.hasVideo?null!=E.videoCodec&&(E.mimeType='video/x-flv; codecs="'+E.videoCodec+","+E.audioCodec+'"'):E.mimeType='video/x-flv; codecs="'+E.audioCodec+'"',E.isComplete()&&this._onMediaInfo(E)}var b=this._parseMP3AudioData(e,t+1,n-1,!1);if(void 0==b)return;var S=this._timestampBase+i,k={unit:b,length:b.byteLength,dts:S,pts:S};f.samples.push(k),f.length+=b.length}}}},{key:"_parseAACAudioData",value:function(e,t,n){if(n<=1)return void l.default.w(this.TAG,"Flv: Invalid AAC packet, missing AACPacketType or/and Data!");var i={},r=new Uint8Array(e,t,n);return i.packetType=r[0],0===r[0]?i.data=this._parseAACAudioSpecificConfig(e,t+1,n-1):i.data=r.subarray(1),i}},{key:"_parseAACAudioSpecificConfig",value:function(e,t,n){var i=new Uint8Array(e,t,n),r=null,s=0,a=0,o=0,u=null;if(s=a=i[0]>>>3,(o=(7&i[0])<<1|i[1]>>>7)<0||o>=this._mpegSamplingRates.length)return void this._onError(m.default.FORMAT_ERROR,"Flv: AAC invalid sampling frequency index!");var l=this._mpegSamplingRates[o],d=(120&i[1])>>>3;if(d<0||d>=8)return void this._onError(m.default.FORMAT_ERROR,"Flv: AAC invalid channel configuration");5===s&&(u=(7&i[1])<<1|i[2]>>>7,i[2]);var h=self.navigator.userAgent.toLowerCase();return-1!==h.indexOf("firefox")?o>=6?(s=5,r=new Array(4),u=o-3):(s=2,r=new Array(2),u=o):-1!==h.indexOf("android")?(s=2,r=new Array(2),u=o):(s=5,u=o,r=new Array(4),o>=6?u=o-3:1===d&&(s=2,r=new Array(2),u=o)),r[0]=s<<3,r[0]|=(15&o)>>>1,r[1]=(15&o)<<7,r[1]|=(15&d)<<3,5===s&&(r[1]|=(15&u)>>>1,r[2]=(1&u)<<7,r[2]|=8,r[3]=0),{config:r,samplingRate:l,channelCount:d,codec:"mp4a.40."+s,originalCodec:"mp4a.40."+a}}},{key:"_parseMP3AudioData",value:function(e,t,n,i){if(n<4)return void l.default.w(this.TAG,"Flv: Invalid MP3 packet, header missing!");var r=(this._littleEndian,new Uint8Array(e,t,n)),s=null;if(i){if(255!==r[0])return;var a=r[1]>>>3&3,o=(6&r[1])>>1,u=(240&r[2])>>>4,d=(12&r[2])>>>2,h=r[3]>>>6&3,f=3!==h?2:1,c=0,_=0;switch(a){case 0:c=this._mpegAudioV25SampleRateTable[d];break;case 2:c=this._mpegAudioV20SampleRateTable[d];break;case 3:c=this._mpegAudioV10SampleRateTable[d]}switch(o){case 1:34,u<this._mpegAudioL3BitRateTable.length&&(_=this._mpegAudioL3BitRateTable[u]);break;case 2:33,u<this._mpegAudioL2BitRateTable.length&&(_=this._mpegAudioL2BitRateTable[u]);break;case 3:32,u<this._mpegAudioL1BitRateTable.length&&(_=this._mpegAudioL1BitRateTable[u])}s={bitRate:_,samplingRate:c,channelCount:f,codec:"mp3",originalCodec:"mp3"}}else s=r;return s}},{key:"_parseVideoData",value:function(e,t,n,i,r){if(n<=1)return void l.default.w(this.TAG,"Flv: Invalid video packet, missing VideoData payload!");if(!0!==this._hasVideoFlagOverrided||!1!==this._hasVideo){var s=new Uint8Array(e,t,n)[0],a=(240&s)>>>4,o=15&s;if(7!==o)return void this._onError(m.default.CODEC_UNSUPPORTED,"Flv: Unsupported codec in video frame: "+o);this._parseAVCVideoPacket(e,t+1,n-1,i,r,a)}}},{key:"_parseAVCVideoPacket",value:function(e,t,n,i,r,s){if(n<4)return void l.default.w(this.TAG,"Flv: Invalid AVC packet, missing AVCPacketType or/and CompositionTime");var a=this._littleEndian,o=new DataView(e,t,n),u=o.getUint8(0),d=16777215&o.getUint32(0,!a),h=d<<8>>8;if(0===u)this._parseAVCDecoderConfigurationRecord(e,t+4,n-4);else if(1===u)this._parseAVCVideoData(e,t+4,n-4,i,r,s,h);else if(2!==u)return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid video packet type "+u)}},{key:"_parseAVCDecoderConfigurationRecord",value:function(e,t,n){if(n<7)return void l.default.w(this.TAG,"Flv: Invalid AVCDecoderConfigurationRecord, lack of data!");var i=this._videoMetadata,r=this._videoTrack,s=this._littleEndian,a=new DataView(e,t,n);i?void 0!==i.avcc&&l.default.w(this.TAG,"Found another AVCDecoderConfigurationRecord!"):(!1===this._hasVideo&&!1===this._hasVideoFlagOverrided&&(this._hasVideo=!0,this._mediaInfo.hasVideo=!0),i=this._videoMetadata={},i.type="video",i.id=r.id,i.timescale=this._timescale,i.duration=this._duration);var o=a.getUint8(0),u=a.getUint8(1);a.getUint8(2),a.getUint8(3);if(1!==o||0===u)return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid AVCDecoderConfigurationRecord");if(this._naluLengthSize=1+(3&a.getUint8(4)),3!==this._naluLengthSize&&4!==this._naluLengthSize)return void this._onError(m.default.FORMAT_ERROR,"Flv: Strange NaluLengthSizeMinusOne: "+(this._naluLengthSize-1));var d=31&a.getUint8(5);if(0===d)return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid AVCDecoderConfigurationRecord: No SPS");d>1&&l.default.w(this.TAG,"Flv: Strange AVCDecoderConfigurationRecord: SPS Count = "+d);for(var h=6,f=0;f<d;f++){var _=a.getUint16(h,!s);if(h+=2,0!==_){var p=new Uint8Array(e,t+h,_);h+=_;var v=c.default.parseSPS(p);if(0===f){i.codecWidth=v.codec_size.width,i.codecHeight=v.codec_size.height,i.presentWidth=v.present_size.width,i.presentHeight=v.present_size.height,i.profile=v.profile_string,i.level=v.level_string,i.bitDepth=v.bit_depth,i.chromaFormat=v.chroma_format,i.sarRatio=v.sar_ratio,i.frameRate=v.frame_rate,!1!==v.frame_rate.fixed&&0!==v.frame_rate.fps_num&&0!==v.frame_rate.fps_den||(i.frameRate=this._referenceFrameRate);var g=i.frameRate.fps_den,y=i.frameRate.fps_num;i.refSampleDuration=i.timescale*(g/y);for(var E=p.subarray(1,4),b="avc1.",S=0;S<3;S++){var k=E[S].toString(16);k.length<2&&(k="0"+k),b+=k}i.codec=b;var L=this._mediaInfo;L.width=i.codecWidth,L.height=i.codecHeight,L.fps=i.frameRate.fps,L.profile=i.profile,L.level=i.level,L.refFrames=v.ref_frames,L.chromaFormat=v.chroma_format_string,L.sarNum=i.sarRatio.width,L.sarDen=i.sarRatio.height,L.videoCodec=b,L.hasAudio?null!=L.audioCodec&&(L.mimeType='video/x-flv; codecs="'+L.videoCodec+","+L.audioCodec+'"'):L.mimeType='video/x-flv; codecs="'+L.videoCodec+'"',L.isComplete()&&this._onMediaInfo(L)}}}var R=a.getUint8(h);if(0===R)return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid AVCDecoderConfigurationRecord: No PPS");R>1&&l.default.w(this.TAG,"Flv: Strange AVCDecoderConfigurationRecord: PPS Count = "+R),h++;for(var A=0;A<R;A++){var w=a.getUint16(h,!s);h+=2,0!==w&&(h+=w)}i.avcc=new Uint8Array(n),i.avcc.set(new Uint8Array(e,t,n),0),l.default.v(this.TAG,"Parsed AVCDecoderConfigurationRecord"),this._isInitialMetadataDispatched()?this._dispatch&&(this._audioTrack.length||this._videoTrack.length)&&this._onDataAvailable(this._audioTrack,this._videoTrack):this._videoInitialMetadataDispatched=!0,this._dispatch=!1,this._onTrackMetadata("video",i)}},{key:"_parseAVCVideoData",value:function(e,t,n,i,r,s,a){for(var o=this._littleEndian,u=new DataView(e,t,n),d=[],h=0,f=0,c=this._naluLengthSize,_=this._timestampBase+i,m=1===s;f<n;){if(f+4>=n){l.default.w(this.TAG,"Malformed Nalu near timestamp "+_+", offset = "+f+", dataSize = "+n);break}var p=u.getUint32(f,!o);if(3===c&&(p>>>=8),p>n-c)return void l.default.w(this.TAG,"Malformed Nalus near timestamp "+_+", NaluSize > DataSize!");var v=31&u.getUint8(f+c);5===v&&(m=!0);var g=new Uint8Array(e,t+f,c+p),y={type:v,data:g};d.push(y),h+=g.byteLength,f+=c+p}if(d.length){var E=this._videoTrack,b={units:d,length:h,isKeyframe:m,dts:_,cts:a,pts:_+a};m&&(b.fileposition=r),E.samples.push(b),E.length+=h}}},{key:"onTrackMetadata",get:function(){return this._onTrackMetadata},set:function(e){this._onTrackMetadata=e}},{key:"onMediaInfo",get:function(){return this._onMediaInfo},set:function(e){this._onMediaInfo=e}},{key:"onMetaDataArrived",get:function(){return this._onMetaDataArrived},set:function(e){this._onMetaDataArrived=e}},{key:"onScriptDataArrived",get:function(){return this._onScriptDataArrived},set:function(e){this._onScriptDataArrived=e}},{key:"onError",get:function(){return this._onError},set:function(e){this._onError=e}},{key:"onDataAvailable",get:function(){return this._onDataAvailable},set:function(e){this._onDataAvailable=e}},{key:"timestampBase",get:function(){return this._timestampBase},set:function(e){this._timestampBase=e}},{key:"overridedDuration",get:function(){return this._duration},set:function(e){this._durationOverrided=!0,this._duration=e,this._mediaInfo.duration=e}},{key:"overridedHasAudio",set:function(e){this._hasAudioFlagOverrided=!0,this._hasAudio=e,this._mediaInfo.hasAudio=e}},{key:"overridedHasVideo",set:function(e){this._hasVideoFlagOverrided=!0,this._hasVideo=e,this._mediaInfo.hasVideo=e}}],[{key:"probe",value:function(e){var t=new Uint8Array(e),n={match:!1};if(70!==t[0]||76!==t[1]||86!==t[2]||1!==t[3])return n;var i=(4&t[4])>>>2!=0,r=0!=(1&t[4]),a=s(t,5);return a<9?n:{match:!0,consumed:a,dataOffset:a,hasAudioTrack:i,hasVideoTrack:r}}}]),e}();n.default=y},{"../core/media-info.js":7,"../utils/exception.js":40,"../utils/logger.js":41,"./amf-parser.js":15,"./demux-errors.js":16,"./sps-parser.js":19}],19:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("./exp-golomb.js"),a=function(e){return e&&e.__esModule?e:{default:e}}(s),o=function(){function e(){i(this,e)}return r(e,null,[{key:"_ebsp2rbsp",value:function(e){for(var t=e,n=t.byteLength,i=new Uint8Array(n),r=0,s=0;s<n;s++)s>=2&&3===t[s]&&0===t[s-1]&&0===t[s-2]||(i[r]=t[s],r++);return new Uint8Array(i.buffer,0,r)}},{key:"parseSPS",value:function(t){var n=e._ebsp2rbsp(t),i=new a.default(n);i.readByte();var r=i.readByte();i.readByte();var s=i.readByte();i.readUEG();var o=e.getProfileString(r),u=e.getLevelString(s),l=1,d=420,h=[0,420,422,444],f=8;if((100===r||110===r||122===r||244===r||44===r||83===r||86===r||118===r||128===r||138===r||144===r)&&(l=i.readUEG(),3===l&&i.readBits(1),l<=3&&(d=h[l]),f=i.readUEG()+8,i.readUEG(),i.readBits(1),i.readBool()))for(var c=3!==l?8:12,_=0;_<c;_++)i.readBool()&&(_<6?e._skipScalingList(i,16):e._skipScalingList(i,64));i.readUEG();var m=i.readUEG();if(0===m)i.readUEG();else if(1===m){i.readBits(1),i.readSEG(),i.readSEG();for(var p=i.readUEG(),v=0;v<p;v++)i.readSEG()}var g=i.readUEG();i.readBits(1);var y=i.readUEG(),E=i.readUEG(),b=i.readBits(1);0===b&&i.readBits(1),i.readBits(1);var S=0,k=0,L=0,R=0;i.readBool()&&(S=i.readUEG(),k=i.readUEG(),L=i.readUEG(),R=i.readUEG());var A=1,w=1,T=0,O=!0,C=0,I=0;if(i.readBool()){if(i.readBool()){var D=i.readByte(),x=[1,12,10,16,40,24,20,32,80,18,15,64,160,4,3,2],M=[1,11,11,11,33,11,11,11,33,11,11,33,99,3,2,1];D>0&&D<16?(A=x[D-1],w=M[D-1]):255===D&&(A=i.readByte()<<8|i.readByte(),w=i.readByte()<<8|i.readByte())}if(i.readBool()&&i.readBool(),i.readBool()&&(i.readBits(4),i.readBool()&&i.readBits(24)),i.readBool()&&(i.readUEG(),i.readUEG()),i.readBool()){var B=i.readBits(32),j=i.readBits(32);O=i.readBool(),C=j,I=2*B,T=C/I}}var P=1;1===A&&1===w||(P=A/w);var U=0,N=0;if(0===l)U=1,N=2-b;else{var F=3===l?1:2,G=1===l?2:1;U=F,N=G*(2-b)}var V=16*(y+1),z=16*(E+1)*(2-b);V-=(S+k)*U,z-=(L+R)*N;var H=Math.ceil(V*P);return i.destroy(),i=null,{profile_string:o,level_string:u,bit_depth:f,ref_frames:g,chroma_format:d,chroma_format_string:e.getChromaFormatString(d),frame_rate:{fixed:O,fps:T,fps_den:I,fps_num:C},sar_ratio:{width:A,height:w},codec_size:{width:V,height:z},present_size:{width:H,height:z}}}},{key:"_skipScalingList",value:function(e,t){for(var n=8,i=8,r=0,s=0;s<t;s++)0!==i&&(r=e.readSEG(),i=(n+r+256)%256),n=0===i?n:i}},{key:"getProfileString",value:function(e){switch(e){case 66:return"Baseline";case 77:return"Main";case 88:return"Extended";case 100:return"High";case 110:return"High10";case 122:return"High422";case 244:return"High444";default:return"Unknown"}}},{key:"getLevelString",value:function(e){return(e/10).toFixed(1)}},{key:"getChromaFormatString",value:function(e){switch(e){case 420:return"4:2:0";case 422:return"4:2:2";case 444:return"4:4:4";default:return"Unknown"}}}]),e}();n.default=o},{"./exp-golomb.js":17}],20:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=e;if(null==n||"object"!==(void 0===n?"undefined":o(n)))throw new S.InvalidArgumentException("MediaDataSource must be an javascript object!");if(!n.hasOwnProperty("type"))throw new S.InvalidArgumentException("MediaDataSource must has type field to indicate video file type!");switch(n.type){case"flv":return new _.default(n,t);default:return new p.default(n,t)}}function s(){return h.default.supportMSEH264Playback()}function a(){return h.default.getFeatureList()}Object.defineProperty(n,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},u=e("./utils/polyfill.js"),l=i(u),d=e("./core/features.js"),h=i(d),f=e("./io/loader.js"),c=e("./player/flv-player.js"),_=i(c),m=e("./player/native-player.js"),p=i(m),v=e("./player/player-events.js"),g=i(v),y=e("./player/player-errors.js"),E=e("./utils/logging-control.js"),b=i(E),S=e("./utils/exception.js");l.default.install();var k={};k.createPlayer=r,k.isSupported=s,k.getFeatureList=a,k.BaseLoader=f.BaseLoader,k.LoaderStatus=f.LoaderStatus,k.LoaderErrors=f.LoaderErrors,k.Events=g.default,k.ErrorTypes=y.ErrorTypes,k.ErrorDetails=y.ErrorDetails,k.FlvPlayer=_.default,k.NativePlayer=p.default,k.LoggingControl=b.default,Object.defineProperty(k,"version",{enumerable:!0,get:function(){return"1.5.0"}}),n.default=k},{"./core/features.js":6,"./io/loader.js":24,"./player/flv-player.js":32,"./player/native-player.js":33,"./player/player-errors.js":34,"./player/player-events.js":35,"./utils/exception.js":40,"./utils/logging-control.js":42,"./utils/polyfill.js":43}],21:[function(e,t,n){"use strict";t.exports=e("./flv.js").default},{"./flv.js":20}],22:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},u=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},l=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),d=e("../utils/logger.js"),h=(i(d),e("../utils/browser.js")),f=i(h),c=e("./loader.js"),_=e("../utils/exception.js"),m=function(e){function t(e,n){r(this,t);var i=s(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"fetch-stream-loader"));return i.TAG="FetchStreamLoader",i._seekHandler=e,i._config=n,i._needStash=!0,i._requestAbort=!1,i._contentLength=null,i._receivedLength=0,i}return a(t,e),l(t,null,[{key:"isSupported",value:function(){try{var e=f.default.msedge&&f.default.version.minor>=15048,t=!f.default.msedge||e;return self.fetch&&self.ReadableStream&&t}catch(e){return!1}}}]),l(t,[{key:"destroy",value:function(){this.isWorking()&&this.abort(),u(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e,t){var n=this;this._dataSource=e,this._range=t;var i=e.url;this._config.reuseRedirectedURL&&void 0!=e.redirectedURL&&(i=e.redirectedURL);var r=this._seekHandler.getConfig(i,t),s=new self.Headers;if("object"===o(r.headers)){var a=r.headers;for(var u in a)a.hasOwnProperty(u)&&s.append(u,a[u])}var l={method:"GET",headers:s,mode:"cors",cache:"default",referrerPolicy:"no-referrer-when-downgrade"};if("object"===o(this._config.headers))for(var d in this._config.headers)s.append(d,this._config.headers[d]);!1===e.cors&&(l.mode="same-origin"),e.withCredentials&&(l.credentials="include"),e.referrerPolicy&&(l.referrerPolicy=e.referrerPolicy),this._status=c.LoaderStatus.kConnecting,self.fetch(r.url,l).then(function(e){if(n._requestAbort)return n._requestAbort=!1,void(n._status=c.LoaderStatus.kIdle);if(e.ok&&e.status>=200&&e.status<=299){if(e.url!==r.url&&n._onURLRedirect){var t=n._seekHandler.removeURLParameters(e.url);n._onURLRedirect(t)}var i=e.headers.get("Content-Length");return null!=i&&(n._contentLength=parseInt(i),0!==n._contentLength&&n._onContentLengthKnown&&n._onContentLengthKnown(n._contentLength)),n._pump.call(n,e.body.getReader())}if(n._status=c.LoaderStatus.kError,!n._onError)throw new _.RuntimeException("FetchStreamLoader: Http code invalid, "+e.status+" "+e.statusText);n._onError(c.LoaderErrors.HTTP_STATUS_CODE_INVALID,{code:e.status,msg:e.statusText})}).catch(function(e){if(n._status=c.LoaderStatus.kError,!n._onError)throw e;n._onError(c.LoaderErrors.EXCEPTION,{code:-1,msg:e.message})})}},{key:"abort",value:function(){this._requestAbort=!0}},{key:"_pump",value:function(e){var t=this;return e.read().then(function(n){if(n.done)if(null!==t._contentLength&&t._receivedLength<t._contentLength){t._status=c.LoaderStatus.kError;var i=c.LoaderErrors.EARLY_EOF,r={code:-1,msg:"Fetch stream meet Early-EOF"};if(!t._onError)throw new _.RuntimeException(r.msg);t._onError(i,r)}else t._status=c.LoaderStatus.kComplete,t._onComplete&&t._onComplete(t._range.from,t._range.from+t._receivedLength-1);else{if(!0===t._requestAbort)return t._requestAbort=!1,t._status=c.LoaderStatus.kComplete,e.cancel();t._status=c.LoaderStatus.kBuffering;var s=n.value.buffer,a=t._range.from+t._receivedLength;t._receivedLength+=s.byteLength,t._onDataArrival&&t._onDataArrival(s,a,t._receivedLength),t._pump(e)}}).catch(function(e){if(11!==e.code||!f.default.msedge){t._status=c.LoaderStatus.kError;var n=0,i=null;if(19!==e.code&&"network error"!==e.message||!(null===t._contentLength||null!==t._contentLength&&t._receivedLength<t._contentLength)?(n=c.LoaderErrors.EXCEPTION,i={code:e.code,msg:e.message}):(n=c.LoaderErrors.EARLY_EOF,i={code:e.code,msg:"Fetch stream meet Early-EOF"}),!t._onError)throw new _.RuntimeException(i.msg);t._onError(n,i)}})}}]),t}(c.BaseLoader);n.default=m},{"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],23:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("../utils/logger.js"),o=i(a),u=e("./speed-sampler.js"),l=i(u),d=e("./loader.js"),h=e("./fetch-stream-loader.js"),f=i(h),c=e("./xhr-moz-chunked-loader.js"),_=i(c),m=e("./xhr-msstream-loader.js"),p=(i(m),e("./xhr-range-loader.js")),v=i(p),g=e("./websocket-loader.js"),y=i(g),E=e("./range-seek-handler.js"),b=i(E),S=e("./param-seek-handler.js"),k=i(S),L=e("../utils/exception.js"),R=function(){function e(t,n,i){r(this,e),this.TAG="IOController",this._config=n,this._extraData=i,this._stashInitialSize=393216,void 0!=n.stashInitialSize&&n.stashInitialSize>0&&(this._stashInitialSize=n.stashInitialSize),this._stashUsed=0,this._stashSize=this._stashInitialSize,this._bufferSize=3145728,this._stashBuffer=new ArrayBuffer(this._bufferSize),this._stashByteStart=0,this._enableStash=!0,!1===n.enableStashBuffer&&(this._enableStash=!1),this._loader=null,this._loaderClass=null,this._seekHandler=null,this._dataSource=t,this._isWebSocketURL=/wss?:\/\/(.+?)/.test(t.url),this._refTotalLength=t.filesize?t.filesize:null,this._totalLength=this._refTotalLength,this._fullRequestFlag=!1,this._currentRange=null,this._redirectedURL=null,this._speedNormalized=0,this._speedSampler=new l.default,this._speedNormalizeList=[64,128,256,384,512,768,1024,1536,2048,3072,4096],this._isEarlyEofReconnecting=!1,this._paused=!1,this._resumeFrom=0,this._onDataArrival=null,this._onSeeked=null,this._onError=null,this._onComplete=null,this._onRedirect=null,this._onRecoveredEarlyEof=null,this._selectSeekHandler(),this._selectLoader(),this._createLoader()}return s(e,[{key:"destroy",value:function(){this._loader.isWorking()&&this._loader.abort(),this._loader.destroy(),this._loader=null,this._loaderClass=null,this._dataSource=null,this._stashBuffer=null,this._stashUsed=this._stashSize=this._bufferSize=this._stashByteStart=0,this._currentRange=null,this._speedSampler=null,this._isEarlyEofReconnecting=!1,this._onDataArrival=null,this._onSeeked=null,this._onError=null,this._onComplete=null,this._onRedirect=null,this._onRecoveredEarlyEof=null,this._extraData=null}},{key:"isWorking",value:function(){return this._loader&&this._loader.isWorking()&&!this._paused}},{key:"isPaused",value:function(){return this._paused}},{key:"_selectSeekHandler",value:function(){var e=this._config;if("range"===e.seekType)this._seekHandler=new b.default(this._config.rangeLoadZeroStart);else if("param"===e.seekType){var t=e.seekParamStart||"bstart",n=e.seekParamEnd||"bend";this._seekHandler=new k.default(t,n)}else{if("custom"!==e.seekType)throw new L.InvalidArgumentException("Invalid seekType in config: "+e.seekType);if("function"!=typeof e.customSeekHandler)throw new L.InvalidArgumentException("Custom seekType specified in config but invalid customSeekHandler!");this._seekHandler=new e.customSeekHandler}}},{key:"_selectLoader",value:function(){if(null!=this._config.customLoader)this._loaderClass=this._config.customLoader;else if(this._isWebSocketURL)this._loaderClass=y.default;else if(f.default.isSupported())this._loaderClass=f.default;else if(_.default.isSupported())this._loaderClass=_.default;else{if(!v.default.isSupported())throw new L.RuntimeException("Your browser doesn't support xhr with arraybuffer responseType!");this._loaderClass=v.default}}},{key:"_createLoader",value:function(){this._loader=new this._loaderClass(this._seekHandler,this._config),!1===this._loader.needStashBuffer&&(this._enableStash=!1),this._loader.onContentLengthKnown=this._onContentLengthKnown.bind(this),this._loader.onURLRedirect=this._onURLRedirect.bind(this),this._loader.onDataArrival=this._onLoaderChunkArrival.bind(this),this._loader.onComplete=this._onLoaderComplete.bind(this),this._loader.onError=this._onLoaderError.bind(this)}},{key:"open",value:function(e){this._currentRange={from:0,to:-1},e&&(this._currentRange.from=e),this._speedSampler.reset(),e||(this._fullRequestFlag=!0),this._loader.open(this._dataSource,Object.assign({},this._currentRange))}},{key:"abort",value:function(){this._loader.abort(),this._paused&&(this._paused=!1,this._resumeFrom=0)}},{key:"pause",value:function(){this.isWorking()&&(this._loader.abort(),0!==this._stashUsed?(this._resumeFrom=this._stashByteStart,this._currentRange.to=this._stashByteStart-1):this._resumeFrom=this._currentRange.to+1,this._stashUsed=0,this._stashByteStart=0,this._paused=!0)}},{key:"resume",value:function(){if(this._paused){this._paused=!1;var e=this._resumeFrom;this._resumeFrom=0,this._internalSeek(e,!0)}}},{key:"seek",value:function(e){this._paused=!1,this._stashUsed=0,this._stashByteStart=0,this._internalSeek(e,!0)}},{key:"_internalSeek",value:function(e,t){this._loader.isWorking()&&this._loader.abort(),this._flushStashBuffer(t),this._loader.destroy(),this._loader=null;var n={from:e,to:-1};this._currentRange={from:n.from,to:-1},this._speedSampler.reset(),this._stashSize=this._stashInitialSize,this._createLoader(),this._loader.open(this._dataSource,n),this._onSeeked&&this._onSeeked()}},{key:"updateUrl",value:function(e){if(!e||"string"!=typeof e||0===e.length)throw new L.InvalidArgumentException("Url must be a non-empty string!");this._dataSource.url=e}},{key:"_expandBuffer",value:function(e){for(var t=this._stashSize;t+1048576<e;)t*=2;if((t+=1048576)!==this._bufferSize){var n=new ArrayBuffer(t);if(this._stashUsed>0){var i=new Uint8Array(this._stashBuffer,0,this._stashUsed);new Uint8Array(n,0,t).set(i,0)}this._stashBuffer=n,this._bufferSize=t}}},{key:"_normalizeSpeed",value:function(e){var t=this._speedNormalizeList,n=t.length-1,i=0,r=0,s=n;if(e<t[0])return t[0];for(;r<=s;){if((i=r+Math.floor((s-r)/2))===n||e>=t[i]&&e<t[i+1])return t[i];t[i]<e?r=i+1:s=i-1}}},{key:"_adjustStashSize",value:function(e){var t=0;(t=this._config.isLive?e:e<512?e:e>=512&&e<=1024?Math.floor(1.5*e):2*e)>8192&&(t=8192);var n=1024*t+1048576;this._bufferSize<n&&this._expandBuffer(n),this._stashSize=1024*t}},{key:"_dispatchChunks",value:function(e,t){return this._currentRange.to=t+e.byteLength-1,this._onDataArrival(e,t)}},{key:"_onURLRedirect",value:function(e){this._redirectedURL=e,this._onRedirect&&this._onRedirect(e)}},{key:"_onContentLengthKnown",value:function(e){e&&this._fullRequestFlag&&(this._totalLength=e,this._fullRequestFlag=!1)}},{key:"_onLoaderChunkArrival",value:function(e,t,n){if(!this._onDataArrival)throw new L.IllegalStateException("IOController: No existing consumer (onDataArrival) callback!");if(!this._paused){this._isEarlyEofReconnecting&&(this._isEarlyEofReconnecting=!1,this._onRecoveredEarlyEof&&this._onRecoveredEarlyEof()),this._speedSampler.addBytes(e.byteLength);var i=this._speedSampler.lastSecondKBps;if(0!==i){var r=this._normalizeSpeed(i);this._speedNormalized!==r&&(this._speedNormalized=r,this._adjustStashSize(r))}if(this._enableStash)if(0===this._stashUsed&&0===this._stashByteStart&&(this._stashByteStart=t),this._stashUsed+e.byteLength<=this._stashSize){var s=new Uint8Array(this._stashBuffer,0,this._stashSize);s.set(new Uint8Array(e),this._stashUsed),this._stashUsed+=e.byteLength}else{var a=new Uint8Array(this._stashBuffer,0,this._bufferSize);if(this._stashUsed>0){var o=this._stashBuffer.slice(0,this._stashUsed),u=this._dispatchChunks(o,this._stashByteStart);if(u<o.byteLength){if(u>0){var l=new Uint8Array(o,u);a.set(l,0),this._stashUsed=l.byteLength,this._stashByteStart+=u}}else this._stashUsed=0,this._stashByteStart+=u;this._stashUsed+e.byteLength>this._bufferSize&&(this._expandBuffer(this._stashUsed+e.byteLength),a=new Uint8Array(this._stashBuffer,0,this._bufferSize)),a.set(new Uint8Array(e),this._stashUsed),this._stashUsed+=e.byteLength}else{var d=this._dispatchChunks(e,t);if(d<e.byteLength){var h=e.byteLength-d;h>this._bufferSize&&(this._expandBuffer(h),a=new Uint8Array(this._stashBuffer,0,this._bufferSize)),a.set(new Uint8Array(e,d),0),this._stashUsed+=h,this._stashByteStart=t+d}}}else if(0===this._stashUsed){var f=this._dispatchChunks(e,t);if(f<e.byteLength){var c=e.byteLength-f;c>this._bufferSize&&this._expandBuffer(c);var _=new Uint8Array(this._stashBuffer,0,this._bufferSize);_.set(new Uint8Array(e,f),0),this._stashUsed+=c,this._stashByteStart=t+f}}else{this._stashUsed+e.byteLength>this._bufferSize&&this._expandBuffer(this._stashUsed+e.byteLength);var m=new Uint8Array(this._stashBuffer,0,this._bufferSize);m.set(new Uint8Array(e),this._stashUsed),this._stashUsed+=e.byteLength;var p=this._dispatchChunks(this._stashBuffer.slice(0,this._stashUsed),this._stashByteStart);if(p<this._stashUsed&&p>0){var v=new Uint8Array(this._stashBuffer,p);m.set(v,0)}this._stashUsed-=p,this._stashByteStart+=p}}}},{key:"_flushStashBuffer",value:function(e){if(this._stashUsed>0){var t=this._stashBuffer.slice(0,this._stashUsed),n=this._dispatchChunks(t,this._stashByteStart),i=t.byteLength-n;if(n<t.byteLength){if(!e){if(n>0){var r=new Uint8Array(this._stashBuffer,0,this._bufferSize),s=new Uint8Array(t,n);r.set(s,0),this._stashUsed=s.byteLength,this._stashByteStart+=n}return 0}o.default.w(this.TAG,i+" bytes unconsumed data remain when flush buffer, dropped")}return this._stashUsed=0,this._stashByteStart=0,i}return 0}},{key:"_onLoaderComplete",value:function(e,t){this._flushStashBuffer(!0),this._onComplete&&this._onComplete(this._extraData)}},{key:"_onLoaderError",value:function(e,t){switch(o.default.e(this.TAG,"Loader error, code = "+t.code+", msg = "+t.msg),this._flushStashBuffer(!1),this._isEarlyEofReconnecting&&(this._isEarlyEofReconnecting=!1,e=d.LoaderErrors.UNRECOVERABLE_EARLY_EOF),e){case d.LoaderErrors.EARLY_EOF:if(!this._config.isLive&&this._totalLength){var n=this._currentRange.to+1;return void(n<this._totalLength&&(o.default.w(this.TAG,"Connection lost, trying reconnect..."),this._isEarlyEofReconnecting=!0,this._internalSeek(n,!1)))}e=d.LoaderErrors.UNRECOVERABLE_EARLY_EOF;break;case d.LoaderErrors.UNRECOVERABLE_EARLY_EOF:case d.LoaderErrors.CONNECTING_TIMEOUT:case d.LoaderErrors.HTTP_STATUS_CODE_INVALID:case d.LoaderErrors.EXCEPTION:}if(!this._onError)throw new L.RuntimeException("IOException: "+t.msg);this._onError(e,t)}},{key:"status",get:function(){return this._loader.status}},{key:"extraData",get:function(){return this._extraData},set:function(e){this._extraData=e}},{key:"onDataArrival",get:function(){return this._onDataArrival},set:function(e){this._onDataArrival=e}},{key:"onSeeked",get:function(){return this._onSeeked},set:function(e){this._onSeeked=e}},{key:"onError",get:function(){return this._onError},set:function(e){this._onError=e}},{key:"onComplete",get:function(){return this._onComplete},set:function(e){this._onComplete=e}},{key:"onRedirect",get:function(){return this._onRedirect},set:function(e){this._onRedirect=e}},{key:"onRecoveredEarlyEof",get:function(){return this._onRecoveredEarlyEof},set:function(e){this._onRecoveredEarlyEof=e}},{key:"currentURL",get:function(){return this._dataSource.url}},{key:"hasRedirect",get:function(){return null!=this._redirectedURL||void 0!=this._dataSource.redirectedURL}},{key:"currentRedirectedURL",get:function(){return this._redirectedURL||this._dataSource.redirectedURL}},{key:"currentSpeed",get:function(){return this._loaderClass===v.default?this._loader.currentSpeed:this._speedSampler.lastSecondKBps}},{key:"loaderType",get:function(){return this._loader.type}}]),e}();n.default=R},{"../utils/exception.js":40,"../utils/logger.js":41,"./fetch-stream-loader.js":22,"./loader.js":24, | |
| 4 | +"./param-seek-handler.js":25,"./range-seek-handler.js":26,"./speed-sampler.js":27,"./websocket-loader.js":28,"./xhr-moz-chunked-loader.js":29,"./xhr-msstream-loader.js":30,"./xhr-range-loader.js":31}],24:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.BaseLoader=n.LoaderErrors=n.LoaderStatus=void 0;var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("../utils/exception.js"),a=n.LoaderStatus={kIdle:0,kConnecting:1,kBuffering:2,kError:3,kComplete:4};n.LoaderErrors={OK:"OK",EXCEPTION:"Exception",HTTP_STATUS_CODE_INVALID:"HttpStatusCodeInvalid",CONNECTING_TIMEOUT:"ConnectingTimeout",EARLY_EOF:"EarlyEof",UNRECOVERABLE_EARLY_EOF:"UnrecoverableEarlyEof"},n.BaseLoader=function(){function e(t){i(this,e),this._type=t||"undefined",this._status=a.kIdle,this._needStash=!1,this._onContentLengthKnown=null,this._onURLRedirect=null,this._onDataArrival=null,this._onError=null,this._onComplete=null}return r(e,[{key:"destroy",value:function(){this._status=a.kIdle,this._onContentLengthKnown=null,this._onURLRedirect=null,this._onDataArrival=null,this._onError=null,this._onComplete=null}},{key:"isWorking",value:function(){return this._status===a.kConnecting||this._status===a.kBuffering}},{key:"open",value:function(e,t){throw new s.NotImplementedException("Unimplemented abstract function!")}},{key:"abort",value:function(){throw new s.NotImplementedException("Unimplemented abstract function!")}},{key:"type",get:function(){return this._type}},{key:"status",get:function(){return this._status}},{key:"needStashBuffer",get:function(){return this._needStash}},{key:"onContentLengthKnown",get:function(){return this._onContentLengthKnown},set:function(e){this._onContentLengthKnown=e}},{key:"onURLRedirect",get:function(){return this._onURLRedirect},set:function(e){this._onURLRedirect=e}},{key:"onDataArrival",get:function(){return this._onDataArrival},set:function(e){this._onDataArrival=e}},{key:"onError",get:function(){return this._onError},set:function(e){this._onError=e}},{key:"onComplete",get:function(){return this._onComplete},set:function(e){this._onComplete=e}}]),e}()},{"../utils/exception.js":40}],25:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(t,n){i(this,e),this._startName=t,this._endName=n}return r(e,[{key:"getConfig",value:function(e,t){var n=e;if(0!==t.from||-1!==t.to){var i=!0;-1===n.indexOf("?")&&(n+="?",i=!1),i&&(n+="&"),n+=this._startName+"="+t.from.toString(),-1!==t.to&&(n+="&"+this._endName+"="+t.to.toString())}return{url:n,headers:{}}}},{key:"removeURLParameters",value:function(e){var t=e.split("?")[0],n=void 0,i=e.indexOf("?");-1!==i&&(n=e.substring(i+1));var r="";if(void 0!=n&&n.length>0)for(var s=n.split("&"),a=0;a<s.length;a++){var o=s[a].split("="),u=a>0;o[0]!==this._startName&&o[0]!==this._endName&&(u&&(r+="&"),r+=s[a])}return 0===r.length?t:t+"?"+r}}]),e}();n.default=s},{}],26:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(t){i(this,e),this._zeroStart=t||!1}return r(e,[{key:"getConfig",value:function(e,t){var n={};if(0!==t.from||-1!==t.to){var i=void 0;i=-1!==t.to?"bytes="+t.from.toString()+"-"+t.to.toString():"bytes="+t.from.toString()+"-",n.Range=i}else this._zeroStart&&(n.Range="bytes=0-");return{url:e,headers:n}}},{key:"removeURLParameters",value:function(e){return e}}]),e}();n.default=s},{}],27:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(){i(this,e),this._firstCheckpoint=0,this._lastCheckpoint=0,this._intervalBytes=0,this._totalBytes=0,this._lastSecondBytes=0,self.performance&&self.performance.now?this._now=self.performance.now.bind(self.performance):this._now=Date.now}return r(e,[{key:"reset",value:function(){this._firstCheckpoint=this._lastCheckpoint=0,this._totalBytes=this._intervalBytes=0,this._lastSecondBytes=0}},{key:"addBytes",value:function(e){0===this._firstCheckpoint?(this._firstCheckpoint=this._now(),this._lastCheckpoint=this._firstCheckpoint,this._intervalBytes+=e,this._totalBytes+=e):this._now()-this._lastCheckpoint<1e3?(this._intervalBytes+=e,this._totalBytes+=e):(this._lastSecondBytes=this._intervalBytes,this._intervalBytes=e,this._totalBytes+=e,this._lastCheckpoint=this._now())}},{key:"currentKBps",get:function(){this.addBytes(0);var e=(this._now()-this._lastCheckpoint)/1e3;return 0==e&&(e=1),this._intervalBytes/e/1024}},{key:"lastSecondKBps",get:function(){return this.addBytes(0),0!==this._lastSecondBytes?this._lastSecondBytes/1024:this._now()-this._lastCheckpoint>=500?this.currentKBps:0}},{key:"averageKBps",get:function(){var e=(this._now()-this._firstCheckpoint)/1e3;return this._totalBytes/e/1024}}]),e}();n.default=s},{}],28:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var a=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},o=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),u=e("../utils/logger.js"),l=(function(e){e&&e.__esModule}(u),e("./loader.js")),d=e("../utils/exception.js"),h=function(e){function t(){i(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"websocket-loader"));return e.TAG="WebSocketLoader",e._needStash=!0,e._ws=null,e._requestAbort=!1,e._receivedLength=0,e}return s(t,e),o(t,null,[{key:"isSupported",value:function(){try{return void 0!==self.WebSocket}catch(e){return!1}}}]),o(t,[{key:"destroy",value:function(){this._ws&&this.abort(),a(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e){try{var t=this._ws=new self.WebSocket(e.url);t.binaryType="arraybuffer",t.onopen=this._onWebSocketOpen.bind(this),t.onclose=this._onWebSocketClose.bind(this),t.onmessage=this._onWebSocketMessage.bind(this),t.onerror=this._onWebSocketError.bind(this),this._status=l.LoaderStatus.kConnecting}catch(e){this._status=l.LoaderStatus.kError;var n={code:e.code,msg:e.message};if(!this._onError)throw new d.RuntimeException(n.msg);this._onError(l.LoaderErrors.EXCEPTION,n)}}},{key:"abort",value:function(){var e=this._ws;!e||0!==e.readyState&&1!==e.readyState||(this._requestAbort=!0,e.close()),this._ws=null,this._status=l.LoaderStatus.kComplete}},{key:"_onWebSocketOpen",value:function(e){this._status=l.LoaderStatus.kBuffering}},{key:"_onWebSocketClose",value:function(e){if(!0===this._requestAbort)return void(this._requestAbort=!1);this._status=l.LoaderStatus.kComplete,this._onComplete&&this._onComplete(0,this._receivedLength-1)}},{key:"_onWebSocketMessage",value:function(e){var t=this;if(e.data instanceof ArrayBuffer)this._dispatchArrayBuffer(e.data);else if(e.data instanceof Blob){var n=new FileReader;n.onload=function(){t._dispatchArrayBuffer(n.result)},n.readAsArrayBuffer(e.data)}else{this._status=l.LoaderStatus.kError;var i={code:-1,msg:"Unsupported WebSocket message type: "+e.data.constructor.name};if(!this._onError)throw new d.RuntimeException(i.msg);this._onError(l.LoaderErrors.EXCEPTION,i)}}},{key:"_dispatchArrayBuffer",value:function(e){var t=e,n=this._receivedLength;this._receivedLength+=t.byteLength,this._onDataArrival&&this._onDataArrival(t,n,this._receivedLength)}},{key:"_onWebSocketError",value:function(e){this._status=l.LoaderStatus.kError;var t={code:e.code,msg:e.message};if(!this._onError)throw new d.RuntimeException(t.msg);this._onError(l.LoaderErrors.EXCEPTION,t)}}]),t}(l.BaseLoader);n.default=h},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],29:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},u=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),l=e("../utils/logger.js"),d=function(e){return e&&e.__esModule?e:{default:e}}(l),h=e("./loader.js"),f=e("../utils/exception.js"),c=function(e){function t(e,n){i(this,t);var s=r(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"xhr-moz-chunked-loader"));return s.TAG="MozChunkedLoader",s._seekHandler=e,s._config=n,s._needStash=!0,s._xhr=null,s._requestAbort=!1,s._contentLength=null,s._receivedLength=0,s}return s(t,e),u(t,null,[{key:"isSupported",value:function(){try{var e=new XMLHttpRequest;return e.open("GET","https://example.com",!0),e.responseType="moz-chunked-arraybuffer","moz-chunked-arraybuffer"===e.responseType}catch(e){return d.default.w("MozChunkedLoader",e.message),!1}}}]),u(t,[{key:"destroy",value:function(){this.isWorking()&&this.abort(),this._xhr&&(this._xhr.onreadystatechange=null,this._xhr.onprogress=null,this._xhr.onloadend=null,this._xhr.onerror=null,this._xhr=null),o(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e,t){this._dataSource=e,this._range=t;var n=e.url;this._config.reuseRedirectedURL&&void 0!=e.redirectedURL&&(n=e.redirectedURL);var i=this._seekHandler.getConfig(n,t);this._requestURL=i.url;var r=this._xhr=new XMLHttpRequest;if(r.open("GET",i.url,!0),r.responseType="moz-chunked-arraybuffer",r.onreadystatechange=this._onReadyStateChange.bind(this),r.onprogress=this._onProgress.bind(this),r.onloadend=this._onLoadEnd.bind(this),r.onerror=this._onXhrError.bind(this),e.withCredentials&&(r.withCredentials=!0),"object"===a(i.headers)){var s=i.headers;for(var o in s)s.hasOwnProperty(o)&&r.setRequestHeader(o,s[o])}if("object"===a(this._config.headers)){var u=this._config.headers;for(var l in u)u.hasOwnProperty(l)&&r.setRequestHeader(l,u[l])}this._status=h.LoaderStatus.kConnecting,r.send()}},{key:"abort",value:function(){this._requestAbort=!0,this._xhr&&this._xhr.abort(),this._status=h.LoaderStatus.kComplete}},{key:"_onReadyStateChange",value:function(e){var t=e.target;if(2===t.readyState){if(void 0!=t.responseURL&&t.responseURL!==this._requestURL&&this._onURLRedirect){var n=this._seekHandler.removeURLParameters(t.responseURL);this._onURLRedirect(n)}if(0!==t.status&&(t.status<200||t.status>299)){if(this._status=h.LoaderStatus.kError,!this._onError)throw new f.RuntimeException("MozChunkedLoader: Http code invalid, "+t.status+" "+t.statusText);this._onError(h.LoaderErrors.HTTP_STATUS_CODE_INVALID,{code:t.status,msg:t.statusText})}else this._status=h.LoaderStatus.kBuffering}}},{key:"_onProgress",value:function(e){if(this._status!==h.LoaderStatus.kError){null===this._contentLength&&null!==e.total&&0!==e.total&&(this._contentLength=e.total,this._onContentLengthKnown&&this._onContentLengthKnown(this._contentLength));var t=e.target.response,n=this._range.from+this._receivedLength;this._receivedLength+=t.byteLength,this._onDataArrival&&this._onDataArrival(t,n,this._receivedLength)}}},{key:"_onLoadEnd",value:function(e){if(!0===this._requestAbort)return void(this._requestAbort=!1);this._status!==h.LoaderStatus.kError&&(this._status=h.LoaderStatus.kComplete,this._onComplete&&this._onComplete(this._range.from,this._range.from+this._receivedLength-1))}},{key:"_onXhrError",value:function(e){this._status=h.LoaderStatus.kError;var t=0,n=null;if(this._contentLength&&e.loaded<this._contentLength?(t=h.LoaderErrors.EARLY_EOF,n={code:-1,msg:"Moz-Chunked stream meet Early-Eof"}):(t=h.LoaderErrors.EXCEPTION,n={code:-1,msg:e.constructor.name+" "+e.type}),!this._onError)throw new f.RuntimeException(n.msg);this._onError(t,n)}}]),t}(h.BaseLoader);n.default=c},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],30:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},u=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),l=e("../utils/logger.js"),d=function(e){return e&&e.__esModule?e:{default:e}}(l),h=e("./loader.js"),f=e("../utils/exception.js"),c=function(e){function t(e,n){i(this,t);var s=r(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"xhr-msstream-loader"));return s.TAG="MSStreamLoader",s._seekHandler=e,s._config=n,s._needStash=!0,s._xhr=null,s._reader=null,s._totalRange=null,s._currentRange=null,s._currentRequestURL=null,s._currentRedirectedURL=null,s._contentLength=null,s._receivedLength=0,s._bufferLimit=16777216,s._lastTimeBufferSize=0,s._isReconnecting=!1,s}return s(t,e),u(t,null,[{key:"isSupported",value:function(){try{if(void 0===self.MSStream||void 0===self.MSStreamReader)return!1;var e=new XMLHttpRequest;return e.open("GET","https://example.com",!0),e.responseType="ms-stream","ms-stream"===e.responseType}catch(e){return d.default.w("MSStreamLoader",e.message),!1}}}]),u(t,[{key:"destroy",value:function(){this.isWorking()&&this.abort(),this._reader&&(this._reader.onprogress=null,this._reader.onload=null,this._reader.onerror=null,this._reader=null),this._xhr&&(this._xhr.onreadystatechange=null,this._xhr=null),o(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e,t){this._internalOpen(e,t,!1)}},{key:"_internalOpen",value:function(e,t,n){this._dataSource=e,n?this._currentRange=t:this._totalRange=t;var i=e.url;this._config.reuseRedirectedURL&&(void 0!=this._currentRedirectedURL?i=this._currentRedirectedURL:void 0!=e.redirectedURL&&(i=e.redirectedURL));var r=this._seekHandler.getConfig(i,t);this._currentRequestURL=r.url;var s=this._reader=new self.MSStreamReader;s.onprogress=this._msrOnProgress.bind(this),s.onload=this._msrOnLoad.bind(this),s.onerror=this._msrOnError.bind(this);var o=this._xhr=new XMLHttpRequest;if(o.open("GET",r.url,!0),o.responseType="ms-stream",o.onreadystatechange=this._xhrOnReadyStateChange.bind(this),o.onerror=this._xhrOnError.bind(this),e.withCredentials&&(o.withCredentials=!0),"object"===a(r.headers)){var u=r.headers;for(var l in u)u.hasOwnProperty(l)&&o.setRequestHeader(l,u[l])}if("object"===a(this._config.headers)){var d=this._config.headers;for(var f in d)d.hasOwnProperty(f)&&o.setRequestHeader(f,d[f])}this._isReconnecting?this._isReconnecting=!1:this._status=h.LoaderStatus.kConnecting,o.send()}},{key:"abort",value:function(){this._internalAbort(),this._status=h.LoaderStatus.kComplete}},{key:"_internalAbort",value:function(){this._reader&&(1===this._reader.readyState&&this._reader.abort(),this._reader.onprogress=null,this._reader.onload=null,this._reader.onerror=null,this._reader=null),this._xhr&&(this._xhr.abort(),this._xhr.onreadystatechange=null,this._xhr=null)}},{key:"_xhrOnReadyStateChange",value:function(e){var t=e.target;if(2===t.readyState)if(t.status>=200&&t.status<=299){if(this._status=h.LoaderStatus.kBuffering,void 0!=t.responseURL){var n=this._seekHandler.removeURLParameters(t.responseURL);t.responseURL!==this._currentRequestURL&&n!==this._currentRedirectedURL&&(this._currentRedirectedURL=n,this._onURLRedirect&&this._onURLRedirect(n))}var i=t.getResponseHeader("Content-Length");if(null!=i&&null==this._contentLength){var r=parseInt(i);r>0&&(this._contentLength=r,this._onContentLengthKnown&&this._onContentLengthKnown(this._contentLength))}}else{if(this._status=h.LoaderStatus.kError,!this._onError)throw new f.RuntimeException("MSStreamLoader: Http code invalid, "+t.status+" "+t.statusText);this._onError(h.LoaderErrors.HTTP_STATUS_CODE_INVALID,{code:t.status,msg:t.statusText})}else if(3===t.readyState&&t.status>=200&&t.status<=299){this._status=h.LoaderStatus.kBuffering;var s=t.response;this._reader.readAsArrayBuffer(s)}}},{key:"_xhrOnError",value:function(e){this._status=h.LoaderStatus.kError;var t=h.LoaderErrors.EXCEPTION,n={code:-1,msg:e.constructor.name+" "+e.type};if(!this._onError)throw new f.RuntimeException(n.msg);this._onError(t,n)}},{key:"_msrOnProgress",value:function(e){var t=e.target,n=t.result;if(null==n)return void this._doReconnectIfNeeded();var i=n.slice(this._lastTimeBufferSize);this._lastTimeBufferSize=n.byteLength;var r=this._totalRange.from+this._receivedLength;this._receivedLength+=i.byteLength,this._onDataArrival&&this._onDataArrival(i,r,this._receivedLength),n.byteLength>=this._bufferLimit&&(d.default.v(this.TAG,"MSStream buffer exceeded max size near "+(r+i.byteLength)+", reconnecting..."),this._doReconnectIfNeeded())}},{key:"_doReconnectIfNeeded",value:function(){if(null==this._contentLength||this._receivedLength<this._contentLength){this._isReconnecting=!0,this._lastTimeBufferSize=0,this._internalAbort();var e={from:this._totalRange.from+this._receivedLength,to:-1};this._internalOpen(this._dataSource,e,!0)}}},{key:"_msrOnLoad",value:function(e){this._status=h.LoaderStatus.kComplete,this._onComplete&&this._onComplete(this._totalRange.from,this._totalRange.from+this._receivedLength-1)}},{key:"_msrOnError",value:function(e){this._status=h.LoaderStatus.kError;var t=0,n=null;if(this._contentLength&&this._receivedLength<this._contentLength?(t=h.LoaderErrors.EARLY_EOF,n={code:-1,msg:"MSStream meet Early-Eof"}):(t=h.LoaderErrors.EARLY_EOF,n={code:-1,msg:e.constructor.name+" "+e.type}),!this._onError)throw new f.RuntimeException(n.msg);this._onError(t,n)}}]),t}(h.BaseLoader);n.default=c},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],31:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},u=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},l=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),d=e("../utils/logger.js"),h=i(d),f=e("./speed-sampler.js"),c=i(f),_=e("./loader.js"),m=e("../utils/exception.js"),p=function(e){function t(e,n){r(this,t);var i=s(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"xhr-range-loader"));return i.TAG="RangeLoader",i._seekHandler=e,i._config=n,i._needStash=!1,i._chunkSizeKBList=[128,256,384,512,768,1024,1536,2048,3072,4096,5120,6144,7168,8192],i._currentChunkSizeKB=384,i._currentSpeedNormalized=0,i._zeroSpeedChunkCount=0,i._xhr=null,i._speedSampler=new c.default,i._requestAbort=!1,i._waitForTotalLength=!1,i._totalLengthReceived=!1,i._currentRequestURL=null,i._currentRedirectedURL=null,i._currentRequestRange=null,i._totalLength=null,i._contentLength=null,i._receivedLength=0,i._lastTimeLoaded=0,i}return a(t,e),l(t,null,[{key:"isSupported",value:function(){try{var e=new XMLHttpRequest;return e.open("GET","https://example.com",!0),e.responseType="arraybuffer","arraybuffer"===e.responseType}catch(e){return h.default.w("RangeLoader",e.message),!1}}}]),l(t,[{key:"destroy",value:function(){this.isWorking()&&this.abort(),this._xhr&&(this._xhr.onreadystatechange=null,this._xhr.onprogress=null,this._xhr.onload=null,this._xhr.onerror=null,this._xhr=null),u(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e,t){this._dataSource=e,this._range=t,this._status=_.LoaderStatus.kConnecting;var n=!1;void 0!=this._dataSource.filesize&&0!==this._dataSource.filesize&&(n=!0,this._totalLength=this._dataSource.filesize),this._totalLengthReceived||n?this._openSubRange():(this._waitForTotalLength=!0,this._internalOpen(this._dataSource,{from:0,to:-1}))}},{key:"_openSubRange",value:function(){var e=1024*this._currentChunkSizeKB,t=this._range.from+this._receivedLength,n=t+e;null!=this._contentLength&&n-this._range.from>=this._contentLength&&(n=this._range.from+this._contentLength-1),this._currentRequestRange={from:t,to:n},this._internalOpen(this._dataSource,this._currentRequestRange)}},{key:"_internalOpen",value:function(e,t){this._lastTimeLoaded=0;var n=e.url;this._config.reuseRedirectedURL&&(void 0!=this._currentRedirectedURL?n=this._currentRedirectedURL:void 0!=e.redirectedURL&&(n=e.redirectedURL));var i=this._seekHandler.getConfig(n,t);this._currentRequestURL=i.url;var r=this._xhr=new XMLHttpRequest;if(r.open("GET",i.url,!0),r.responseType="arraybuffer",r.onreadystatechange=this._onReadyStateChange.bind(this),r.onprogress=this._onProgress.bind(this),r.onload=this._onLoad.bind(this),r.onerror=this._onXhrError.bind(this),e.withCredentials&&(r.withCredentials=!0),"object"===o(i.headers)){var s=i.headers;for(var a in s)s.hasOwnProperty(a)&&r.setRequestHeader(a,s[a])}if("object"===o(this._config.headers)){var u=this._config.headers;for(var l in u)u.hasOwnProperty(l)&&r.setRequestHeader(l,u[l])}r.send()}},{key:"abort",value:function(){this._requestAbort=!0,this._internalAbort(),this._status=_.LoaderStatus.kComplete}},{key:"_internalAbort",value:function(){this._xhr&&(this._xhr.onreadystatechange=null,this._xhr.onprogress=null,this._xhr.onload=null,this._xhr.onerror=null,this._xhr.abort(),this._xhr=null)}},{key:"_onReadyStateChange",value:function(e){var t=e.target;if(2===t.readyState){if(void 0!=t.responseURL){var n=this._seekHandler.removeURLParameters(t.responseURL);t.responseURL!==this._currentRequestURL&&n!==this._currentRedirectedURL&&(this._currentRedirectedURL=n,this._onURLRedirect&&this._onURLRedirect(n))}if(t.status>=200&&t.status<=299){if(this._waitForTotalLength)return;this._status=_.LoaderStatus.kBuffering}else{if(this._status=_.LoaderStatus.kError,!this._onError)throw new m.RuntimeException("RangeLoader: Http code invalid, "+t.status+" "+t.statusText);this._onError(_.LoaderErrors.HTTP_STATUS_CODE_INVALID,{code:t.status,msg:t.statusText})}}}},{key:"_onProgress",value:function(e){if(this._status!==_.LoaderStatus.kError){if(null===this._contentLength){var t=!1;if(this._waitForTotalLength){this._waitForTotalLength=!1,this._totalLengthReceived=!0,t=!0;var n=e.total;this._internalAbort(),null!=n&0!==n&&(this._totalLength=n)}if(-1===this._range.to?this._contentLength=this._totalLength-this._range.from:this._contentLength=this._range.to-this._range.from+1,t)return void this._openSubRange();this._onContentLengthKnown&&this._onContentLengthKnown(this._contentLength)}var i=e.loaded-this._lastTimeLoaded;this._lastTimeLoaded=e.loaded,this._speedSampler.addBytes(i)}}},{key:"_normalizeSpeed",value:function(e){var t=this._chunkSizeKBList,n=t.length-1,i=0,r=0,s=n;if(e<t[0])return t[0];for(;r<=s;){if((i=r+Math.floor((s-r)/2))===n||e>=t[i]&&e<t[i+1])return t[i];t[i]<e?r=i+1:s=i-1}}},{key:"_onLoad",value:function(e){if(this._status!==_.LoaderStatus.kError){if(this._waitForTotalLength)return void(this._waitForTotalLength=!1);this._lastTimeLoaded=0;var t=this._speedSampler.lastSecondKBps;if(0===t&&++this._zeroSpeedChunkCount>=3&&(t=this._speedSampler.currentKBps),0!==t){var n=this._normalizeSpeed(t);this._currentSpeedNormalized!==n&&(this._currentSpeedNormalized=n,this._currentChunkSizeKB=n)}var i=e.target.response,r=this._range.from+this._receivedLength;this._receivedLength+=i.byteLength;var s=!1;null!=this._contentLength&&this._receivedLength<this._contentLength?this._openSubRange():s=!0,this._onDataArrival&&this._onDataArrival(i,r,this._receivedLength),s&&(this._status=_.LoaderStatus.kComplete,this._onComplete&&this._onComplete(this._range.from,this._range.from+this._receivedLength-1))}}},{key:"_onXhrError",value:function(e){this._status=_.LoaderStatus.kError;var t=0,n=null;if(this._contentLength&&this._receivedLength>0&&this._receivedLength<this._contentLength?(t=_.LoaderErrors.EARLY_EOF,n={code:-1,msg:"RangeLoader meet Early-Eof"}):(t=_.LoaderErrors.EXCEPTION,n={code:-1,msg:e.constructor.name+" "+e.type}),!this._onError)throw new m.RuntimeException(n.msg);this._onError(t,n)}},{key:"currentSpeed",get:function(){return this._speedSampler.lastSecondKBps}}]),t}(_.BaseLoader);n.default=p},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24,"./speed-sampler.js":27}],32:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),o=e("events"),u=i(o),l=e("../utils/logger.js"),d=i(l),h=e("../utils/browser.js"),f=i(h),c=e("./player-events.js"),_=i(c),m=e("../core/transmuxer.js"),p=i(m),v=e("../core/transmuxing-events.js"),g=i(v),y=e("../core/mse-controller.js"),E=i(y),b=e("../core/mse-events.js"),S=i(b),k=e("./player-errors.js"),L=e("../config.js"),R=e("../utils/exception.js"),A=function(){function e(t,n){if(r(this,e),this.TAG="FlvPlayer",this._type="FlvPlayer",this._emitter=new u.default,this._config=(0,L.createDefaultConfig)(),"object"===(void 0===n?"undefined":s(n))&&Object.assign(this._config,n),"flv"!==t.type.toLowerCase())throw new R.InvalidArgumentException("FlvPlayer requires an flv MediaDataSource input!");!0===t.isLive&&(this._config.isLive=!0),this.e={onvLoadedMetadata:this._onvLoadedMetadata.bind(this),onvSeeking:this._onvSeeking.bind(this),onvCanPlay:this._onvCanPlay.bind(this),onvStalled:this._onvStalled.bind(this),onvProgress:this._onvProgress.bind(this)},self.performance&&self.performance.now?this._now=self.performance.now.bind(self.performance):this._now=Date.now,this._pendingSeekTime=null,this._requestSetTime=!1,this._seekpointRecord=null,this._progressChecker=null,this._mediaDataSource=t,this._mediaElement=null,this._msectl=null,this._transmuxer=null,this._mseSourceOpened=!1,this._hasPendingLoad=!1,this._receivedCanPlay=!1,this._mediaInfo=null,this._statisticsInfo=null;var i=f.default.chrome&&(f.default.version.major<50||50===f.default.version.major&&f.default.version.build<2661);this._alwaysSeekKeyframe=!!(i||f.default.msedge||f.default.msie),this._alwaysSeekKeyframe&&(this._config.accurateSeek=!1)}return a(e,[{key:"destroy",value:function(){null!=this._progressChecker&&(window.clearInterval(this._progressChecker),this._progressChecker=null),this._transmuxer&&this.unload(),this._mediaElement&&this.detachMediaElement(),this.e=null,this._mediaDataSource=null,this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){var n=this;e===_.default.MEDIA_INFO?null!=this._mediaInfo&&Promise.resolve().then(function(){n._emitter.emit(_.default.MEDIA_INFO,n.mediaInfo)}):e===_.default.STATISTICS_INFO&&null!=this._statisticsInfo&&Promise.resolve().then(function(){n._emitter.emit(_.default.STATISTICS_INFO,n.statisticsInfo)}),this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{ | |
| 5 | +key:"attachMediaElement",value:function(e){var t=this;if(this._mediaElement=e,e.addEventListener("loadedmetadata",this.e.onvLoadedMetadata),e.addEventListener("seeking",this.e.onvSeeking),e.addEventListener("canplay",this.e.onvCanPlay),e.addEventListener("stalled",this.e.onvStalled),e.addEventListener("progress",this.e.onvProgress),this._msectl=new E.default(this._config),this._msectl.on(S.default.UPDATE_END,this._onmseUpdateEnd.bind(this)),this._msectl.on(S.default.BUFFER_FULL,this._onmseBufferFull.bind(this)),this._msectl.on(S.default.SOURCE_OPEN,function(){t._mseSourceOpened=!0,t._hasPendingLoad&&(t._hasPendingLoad=!1,t.load())}),this._msectl.on(S.default.ERROR,function(e){t._emitter.emit(_.default.ERROR,k.ErrorTypes.MEDIA_ERROR,k.ErrorDetails.MEDIA_MSE_ERROR,e)}),this._msectl.attachMediaElement(e),null!=this._pendingSeekTime)try{e.currentTime=this._pendingSeekTime,this._pendingSeekTime=null}catch(e){}}},{key:"detachMediaElement",value:function(){this._mediaElement&&(this._msectl.detachMediaElement(),this._mediaElement.removeEventListener("loadedmetadata",this.e.onvLoadedMetadata),this._mediaElement.removeEventListener("seeking",this.e.onvSeeking),this._mediaElement.removeEventListener("canplay",this.e.onvCanPlay),this._mediaElement.removeEventListener("stalled",this.e.onvStalled),this._mediaElement.removeEventListener("progress",this.e.onvProgress),this._mediaElement=null),this._msectl&&(this._msectl.destroy(),this._msectl=null)}},{key:"load",value:function(){var e=this;if(!this._mediaElement)throw new R.IllegalStateException("HTMLMediaElement must be attached before load()!");if(this._transmuxer)throw new R.IllegalStateException("FlvPlayer.load() has been called, please call unload() first!");if(!this._hasPendingLoad){if(this._config.deferLoadAfterSourceOpen&&!1===this._mseSourceOpened)return void(this._hasPendingLoad=!0);this._mediaElement.readyState>0&&(this._requestSetTime=!0,this._mediaElement.currentTime=0),this._transmuxer=new p.default(this._mediaDataSource,this._config),this._transmuxer.on(g.default.INIT_SEGMENT,function(t,n){e._msectl.appendInitSegment(n)}),this._transmuxer.on(g.default.MEDIA_SEGMENT,function(t,n){if(e._msectl.appendMediaSegment(n),e._config.lazyLoad&&!e._config.isLive){var i=e._mediaElement.currentTime;n.info.endDts>=1e3*(i+e._config.lazyLoadMaxDuration)&&null==e._progressChecker&&(d.default.v(e.TAG,"Maximum buffering duration exceeded, suspend transmuxing task"),e._suspendTransmuxer())}}),this._transmuxer.on(g.default.LOADING_COMPLETE,function(){e._msectl.endOfStream(),e._emitter.emit(_.default.LOADING_COMPLETE)}),this._transmuxer.on(g.default.RECOVERED_EARLY_EOF,function(){e._emitter.emit(_.default.RECOVERED_EARLY_EOF)}),this._transmuxer.on(g.default.IO_ERROR,function(t,n){e._emitter.emit(_.default.ERROR,k.ErrorTypes.NETWORK_ERROR,t,n)}),this._transmuxer.on(g.default.DEMUX_ERROR,function(t,n){e._emitter.emit(_.default.ERROR,k.ErrorTypes.MEDIA_ERROR,t,{code:-1,msg:n})}),this._transmuxer.on(g.default.MEDIA_INFO,function(t){e._mediaInfo=t,e._emitter.emit(_.default.MEDIA_INFO,Object.assign({},t))}),this._transmuxer.on(g.default.METADATA_ARRIVED,function(t){e._emitter.emit(_.default.METADATA_ARRIVED,t)}),this._transmuxer.on(g.default.SCRIPTDATA_ARRIVED,function(t){e._emitter.emit(_.default.SCRIPTDATA_ARRIVED,t)}),this._transmuxer.on(g.default.STATISTICS_INFO,function(t){e._statisticsInfo=e._fillStatisticsInfo(t),e._emitter.emit(_.default.STATISTICS_INFO,Object.assign({},e._statisticsInfo))}),this._transmuxer.on(g.default.RECOMMEND_SEEKPOINT,function(t){e._mediaElement&&!e._config.accurateSeek&&(e._requestSetTime=!0,e._mediaElement.currentTime=t/1e3)}),this._transmuxer.open()}}},{key:"unload",value:function(){this._mediaElement&&this._mediaElement.pause(),this._msectl&&this._msectl.seek(0),this._transmuxer&&(this._transmuxer.close(),this._transmuxer.destroy(),this._transmuxer=null)}},{key:"play",value:function(){return this._mediaElement.play()}},{key:"pause",value:function(){this._mediaElement.pause()}},{key:"_fillStatisticsInfo",value:function(e){if(e.playerType=this._type,!(this._mediaElement instanceof HTMLVideoElement))return e;var t=!0,n=0,i=0;if(this._mediaElement.getVideoPlaybackQuality){var r=this._mediaElement.getVideoPlaybackQuality();n=r.totalVideoFrames,i=r.droppedVideoFrames}else void 0!=this._mediaElement.webkitDecodedFrameCount?(n=this._mediaElement.webkitDecodedFrameCount,i=this._mediaElement.webkitDroppedFrameCount):t=!1;return t&&(e.decodedFrames=n,e.droppedFrames=i),e}},{key:"_onmseUpdateEnd",value:function(){if(this._config.lazyLoad&&!this._config.isLive){for(var e=this._mediaElement.buffered,t=this._mediaElement.currentTime,n=0,i=0;i<e.length;i++){var r=e.start(i),s=e.end(i);if(r<=t&&t<s){r,n=s;break}}n>=t+this._config.lazyLoadMaxDuration&&null==this._progressChecker&&(d.default.v(this.TAG,"Maximum buffering duration exceeded, suspend transmuxing task"),this._suspendTransmuxer())}}},{key:"_onmseBufferFull",value:function(){d.default.v(this.TAG,"MSE SourceBuffer is full, suspend transmuxing task"),null==this._progressChecker&&this._suspendTransmuxer()}},{key:"_suspendTransmuxer",value:function(){this._transmuxer&&(this._transmuxer.pause(),null==this._progressChecker&&(this._progressChecker=window.setInterval(this._checkProgressAndResume.bind(this),1e3)))}},{key:"_checkProgressAndResume",value:function(){for(var e=this._mediaElement.currentTime,t=this._mediaElement.buffered,n=!1,i=0;i<t.length;i++){var r=t.start(i),s=t.end(i);if(e>=r&&e<s){e>=s-this._config.lazyLoadRecoverDuration&&(n=!0);break}}n&&(window.clearInterval(this._progressChecker),this._progressChecker=null,n&&(d.default.v(this.TAG,"Continue loading from paused position"),this._transmuxer.resume()))}},{key:"_isTimepointBuffered",value:function(e){for(var t=this._mediaElement.buffered,n=0;n<t.length;n++){var i=t.start(n),r=t.end(n);if(e>=i&&e<r)return!0}return!1}},{key:"_internalSeek",value:function(e){var t=this._isTimepointBuffered(e),n=!1,i=0;if(e<1&&this._mediaElement.buffered.length>0){var r=this._mediaElement.buffered.start(0);(r<1&&e<r||f.default.safari)&&(n=!0,i=f.default.safari?.1:r)}if(n)this._requestSetTime=!0,this._mediaElement.currentTime=i;else if(t){if(this._alwaysSeekKeyframe){var s=this._msectl.getNearestKeyframe(Math.floor(1e3*e));this._requestSetTime=!0,this._mediaElement.currentTime=null!=s?s.dts/1e3:e}else this._requestSetTime=!0,this._mediaElement.currentTime=e;null!=this._progressChecker&&this._checkProgressAndResume()}else null!=this._progressChecker&&(window.clearInterval(this._progressChecker),this._progressChecker=null),this._msectl.seek(e),this._transmuxer.seek(Math.floor(1e3*e)),this._config.accurateSeek&&(this._requestSetTime=!0,this._mediaElement.currentTime=e)}},{key:"_checkAndApplyUnbufferedSeekpoint",value:function(){if(this._seekpointRecord)if(this._seekpointRecord.recordTime<=this._now()-100){var e=this._mediaElement.currentTime;this._seekpointRecord=null,this._isTimepointBuffered(e)||(null!=this._progressChecker&&(window.clearTimeout(this._progressChecker),this._progressChecker=null),this._msectl.seek(e),this._transmuxer.seek(Math.floor(1e3*e)),this._config.accurateSeek&&(this._requestSetTime=!0,this._mediaElement.currentTime=e))}else window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this),50)}},{key:"_checkAndResumeStuckPlayback",value:function(e){var t=this._mediaElement;if(e||!this._receivedCanPlay||t.readyState<2){var n=t.buffered;n.length>0&&t.currentTime<n.start(0)&&(d.default.w(this.TAG,"Playback seems stuck at "+t.currentTime+", seek to "+n.start(0)),this._requestSetTime=!0,this._mediaElement.currentTime=n.start(0),this._mediaElement.removeEventListener("progress",this.e.onvProgress))}else this._mediaElement.removeEventListener("progress",this.e.onvProgress)}},{key:"_onvLoadedMetadata",value:function(e){null!=this._pendingSeekTime&&(this._mediaElement.currentTime=this._pendingSeekTime,this._pendingSeekTime=null)}},{key:"_onvSeeking",value:function(e){var t=this._mediaElement.currentTime,n=this._mediaElement.buffered;if(this._requestSetTime)return void(this._requestSetTime=!1);if(t<1&&n.length>0){var i=n.start(0);if(i<1&&t<i||f.default.safari)return this._requestSetTime=!0,void(this._mediaElement.currentTime=f.default.safari?.1:i)}if(this._isTimepointBuffered(t)){if(this._alwaysSeekKeyframe){var r=this._msectl.getNearestKeyframe(Math.floor(1e3*t));null!=r&&(this._requestSetTime=!0,this._mediaElement.currentTime=r.dts/1e3)}return void(null!=this._progressChecker&&this._checkProgressAndResume())}this._seekpointRecord={seekPoint:t,recordTime:this._now()},window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this),50)}},{key:"_onvCanPlay",value:function(e){this._receivedCanPlay=!0,this._mediaElement.removeEventListener("canplay",this.e.onvCanPlay)}},{key:"_onvStalled",value:function(e){this._checkAndResumeStuckPlayback(!0)}},{key:"_onvProgress",value:function(e){this._checkAndResumeStuckPlayback()}},{key:"type",get:function(){return this._type}},{key:"buffered",get:function(){return this._mediaElement.buffered}},{key:"duration",get:function(){return this._mediaElement.duration}},{key:"volume",get:function(){return this._mediaElement.volume},set:function(e){this._mediaElement.volume=e}},{key:"muted",get:function(){return this._mediaElement.muted},set:function(e){this._mediaElement.muted=e}},{key:"currentTime",get:function(){return this._mediaElement?this._mediaElement.currentTime:0},set:function(e){this._mediaElement?this._internalSeek(e):this._pendingSeekTime=e}},{key:"mediaInfo",get:function(){return Object.assign({},this._mediaInfo)}},{key:"statisticsInfo",get:function(){return null==this._statisticsInfo&&(this._statisticsInfo={}),this._statisticsInfo=this._fillStatisticsInfo(this._statisticsInfo),Object.assign({},this._statisticsInfo)}}]),e}();n.default=A},{"../config.js":5,"../core/mse-controller.js":9,"../core/mse-events.js":10,"../core/transmuxer.js":11,"../core/transmuxing-events.js":13,"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./player-errors.js":34,"./player-events.js":35,events:2}],33:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),o=e("events"),u=i(o),l=e("./player-events.js"),d=i(l),h=e("../config.js"),f=e("../utils/exception.js"),c=function(){function e(t,n){if(r(this,e),this.TAG="NativePlayer",this._type="NativePlayer",this._emitter=new u.default,this._config=(0,h.createDefaultConfig)(),"object"===(void 0===n?"undefined":s(n))&&Object.assign(this._config,n),"flv"===t.type.toLowerCase())throw new f.InvalidArgumentException("NativePlayer does't support flv MediaDataSource input!");if(t.hasOwnProperty("segments"))throw new f.InvalidArgumentException("NativePlayer("+t.type+") doesn't support multipart playback!");this.e={onvLoadedMetadata:this._onvLoadedMetadata.bind(this)},this._pendingSeekTime=null,this._statisticsReporter=null,this._mediaDataSource=t,this._mediaElement=null}return a(e,[{key:"destroy",value:function(){this._mediaElement&&(this.unload(),this.detachMediaElement()),this.e=null,this._mediaDataSource=null,this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){var n=this;e===d.default.MEDIA_INFO?null!=this._mediaElement&&0!==this._mediaElement.readyState&&Promise.resolve().then(function(){n._emitter.emit(d.default.MEDIA_INFO,n.mediaInfo)}):e===d.default.STATISTICS_INFO&&null!=this._mediaElement&&0!==this._mediaElement.readyState&&Promise.resolve().then(function(){n._emitter.emit(d.default.STATISTICS_INFO,n.statisticsInfo)}),this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{key:"attachMediaElement",value:function(e){if(this._mediaElement=e,e.addEventListener("loadedmetadata",this.e.onvLoadedMetadata),null!=this._pendingSeekTime)try{e.currentTime=this._pendingSeekTime,this._pendingSeekTime=null}catch(e){}}},{key:"detachMediaElement",value:function(){this._mediaElement&&(this._mediaElement.src="",this._mediaElement.removeAttribute("src"),this._mediaElement.removeEventListener("loadedmetadata",this.e.onvLoadedMetadata),this._mediaElement=null),null!=this._statisticsReporter&&(window.clearInterval(this._statisticsReporter),this._statisticsReporter=null)}},{key:"load",value:function(){if(!this._mediaElement)throw new f.IllegalStateException("HTMLMediaElement must be attached before load()!");this._mediaElement.src=this._mediaDataSource.url,this._mediaElement.readyState>0&&(this._mediaElement.currentTime=0),this._mediaElement.preload="auto",this._mediaElement.load(),this._statisticsReporter=window.setInterval(this._reportStatisticsInfo.bind(this),this._config.statisticsInfoReportInterval)}},{key:"unload",value:function(){this._mediaElement&&(this._mediaElement.src="",this._mediaElement.removeAttribute("src")),null!=this._statisticsReporter&&(window.clearInterval(this._statisticsReporter),this._statisticsReporter=null)}},{key:"play",value:function(){return this._mediaElement.play()}},{key:"pause",value:function(){this._mediaElement.pause()}},{key:"_onvLoadedMetadata",value:function(e){null!=this._pendingSeekTime&&(this._mediaElement.currentTime=this._pendingSeekTime,this._pendingSeekTime=null),this._emitter.emit(d.default.MEDIA_INFO,this.mediaInfo)}},{key:"_reportStatisticsInfo",value:function(){this._emitter.emit(d.default.STATISTICS_INFO,this.statisticsInfo)}},{key:"type",get:function(){return this._type}},{key:"buffered",get:function(){return this._mediaElement.buffered}},{key:"duration",get:function(){return this._mediaElement.duration}},{key:"volume",get:function(){return this._mediaElement.volume},set:function(e){this._mediaElement.volume=e}},{key:"muted",get:function(){return this._mediaElement.muted},set:function(e){this._mediaElement.muted=e}},{key:"currentTime",get:function(){return this._mediaElement?this._mediaElement.currentTime:0},set:function(e){this._mediaElement?this._mediaElement.currentTime=e:this._pendingSeekTime=e}},{key:"mediaInfo",get:function(){var e=this._mediaElement instanceof HTMLAudioElement?"audio/":"video/",t={mimeType:e+this._mediaDataSource.type};return this._mediaElement&&(t.duration=Math.floor(1e3*this._mediaElement.duration),this._mediaElement instanceof HTMLVideoElement&&(t.width=this._mediaElement.videoWidth,t.height=this._mediaElement.videoHeight)),t}},{key:"statisticsInfo",get:function(){var e={playerType:this._type,url:this._mediaDataSource.url};if(!(this._mediaElement instanceof HTMLVideoElement))return e;var t=!0,n=0,i=0;if(this._mediaElement.getVideoPlaybackQuality){var r=this._mediaElement.getVideoPlaybackQuality();n=r.totalVideoFrames,i=r.droppedVideoFrames}else void 0!=this._mediaElement.webkitDecodedFrameCount?(n=this._mediaElement.webkitDecodedFrameCount,i=this._mediaElement.webkitDroppedFrameCount):t=!1;return t&&(e.decodedFrames=n,e.droppedFrames=i),e}}]),e}();n.default=c},{"../config.js":5,"../utils/exception.js":40,"./player-events.js":35,events:2}],34:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.ErrorDetails=n.ErrorTypes=void 0;var i=e("../io/loader.js"),r=e("../demux/demux-errors.js"),s=function(e){return e&&e.__esModule?e:{default:e}}(r);n.ErrorTypes={NETWORK_ERROR:"NetworkError",MEDIA_ERROR:"MediaError",OTHER_ERROR:"OtherError"},n.ErrorDetails={NETWORK_EXCEPTION:i.LoaderErrors.EXCEPTION,NETWORK_STATUS_CODE_INVALID:i.LoaderErrors.HTTP_STATUS_CODE_INVALID,NETWORK_TIMEOUT:i.LoaderErrors.CONNECTING_TIMEOUT,NETWORK_UNRECOVERABLE_EARLY_EOF:i.LoaderErrors.UNRECOVERABLE_EARLY_EOF,MEDIA_MSE_ERROR:"MediaMSEError",MEDIA_FORMAT_ERROR:s.default.FORMAT_ERROR,MEDIA_FORMAT_UNSUPPORTED:s.default.FORMAT_UNSUPPORTED,MEDIA_CODEC_UNSUPPORTED:s.default.CODEC_UNSUPPORTED}},{"../demux/demux-errors.js":16,"../io/loader.js":24}],35:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={ERROR:"error",LOADING_COMPLETE:"loading_complete",RECOVERED_EARLY_EOF:"recovered_early_eof",MEDIA_INFO:"media_info",METADATA_ARRIVED:"metadata_arrived",SCRIPTDATA_ARRIVED:"scriptdata_arrived",STATISTICS_INFO:"statistics_info"};n.default=i},{}],36:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(){i(this,e)}return r(e,null,[{key:"getSilentFrame",value:function(e,t){if("mp4a.40.2"===e){if(1===t)return new Uint8Array([0,200,0,128,35,128]);if(2===t)return new Uint8Array([33,0,73,144,2,25,0,35,128]);if(3===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,142]);if(4===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,128,44,128,8,2,56]);if(5===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,56]);if(6===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,0,178,0,32,8,224])}else{if(1===t)return new Uint8Array([1,64,34,128,163,78,230,128,186,8,0,0,0,28,6,241,193,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(2===t)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(3===t)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94])}return null}}]),e}();n.default=s},{}],37:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(){i(this,e)}return r(e,null,[{key:"init",value:function(){e.types={avc1:[],avcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],mvex:[],mvhd:[],sdtp:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[],smhd:[],".mp3":[]};for(var t in e.types)e.types.hasOwnProperty(t)&&(e.types[t]=[t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2),t.charCodeAt(3)]);var n=e.constants={};n.FTYP=new Uint8Array([105,115,111,109,0,0,0,1,105,115,111,109,97,118,99,49]),n.STSD_PREFIX=new Uint8Array([0,0,0,0,0,0,0,1]),n.STTS=new Uint8Array([0,0,0,0,0,0,0,0]),n.STSC=n.STCO=n.STTS,n.STSZ=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),n.HDLR_VIDEO=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),n.HDLR_AUDIO=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]),n.DREF=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),n.SMHD=new Uint8Array([0,0,0,0,0,0,0,0]),n.VMHD=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0])}},{key:"box",value:function(e){for(var t=8,n=null,i=Array.prototype.slice.call(arguments,1),r=i.length,s=0;s<r;s++)t+=i[s].byteLength;n=new Uint8Array(t),n[0]=t>>>24&255,n[1]=t>>>16&255,n[2]=t>>>8&255,n[3]=255&t,n.set(e,4);for(var a=8,o=0;o<r;o++)n.set(i[o],a),a+=i[o].byteLength;return n}},{key:"generateInitSegment",value:function(t){var n=e.box(e.types.ftyp,e.constants.FTYP),i=e.moov(t),r=new Uint8Array(n.byteLength+i.byteLength);return r.set(n,0),r.set(i,n.byteLength),r}},{key:"moov",value:function(t){var n=e.mvhd(t.timescale,t.duration),i=e.trak(t),r=e.mvex(t);return e.box(e.types.moov,n,i,r)}},{key:"mvhd",value:function(t,n){return e.box(e.types.mvhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t,n>>>24&255,n>>>16&255,n>>>8&255,255&n,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]))}},{key:"trak",value:function(t){return e.box(e.types.trak,e.tkhd(t),e.mdia(t))}},{key:"tkhd",value:function(t){var n=t.id,i=t.duration,r=t.presentWidth,s=t.presentHeight;return e.box(e.types.tkhd,new Uint8Array([0,0,0,7,0,0,0,0,0,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n,0,0,0,0,i>>>24&255,i>>>16&255,i>>>8&255,255&i,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,r>>>8&255,255&r,0,0,s>>>8&255,255&s,0,0]))}},{key:"mdia",value:function(t){return e.box(e.types.mdia,e.mdhd(t),e.hdlr(t),e.minf(t))}},{key:"mdhd",value:function(t){var n=t.timescale,i=t.duration;return e.box(e.types.mdhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n,i>>>24&255,i>>>16&255,i>>>8&255,255&i,85,196,0,0]))}},{key:"hdlr",value:function(t){var n=null;return n="audio"===t.type?e.constants.HDLR_AUDIO:e.constants.HDLR_VIDEO,e.box(e.types.hdlr,n)}},{key:"minf",value:function(t){var n=null;return n="audio"===t.type?e.box(e.types.smhd,e.constants.SMHD):e.box(e.types.vmhd,e.constants.VMHD),e.box(e.types.minf,n,e.dinf(),e.stbl(t))}},{key:"dinf",value:function(){return e.box(e.types.dinf,e.box(e.types.dref,e.constants.DREF))}},{key:"stbl",value:function(t){return e.box(e.types.stbl,e.stsd(t),e.box(e.types.stts,e.constants.STTS),e.box(e.types.stsc,e.constants.STSC),e.box(e.types.stsz,e.constants.STSZ),e.box(e.types.stco,e.constants.STCO))}},{key:"stsd",value:function(t){return"audio"===t.type?"mp3"===t.codec?e.box(e.types.stsd,e.constants.STSD_PREFIX,e.mp3(t)):e.box(e.types.stsd,e.constants.STSD_PREFIX,e.mp4a(t)):e.box(e.types.stsd,e.constants.STSD_PREFIX,e.avc1(t))}},{key:"mp3",value:function(t){var n=t.channelCount,i=t.audioSampleRate,r=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,n,0,16,0,0,0,0,i>>>8&255,255&i,0,0]);return e.box(e.types[".mp3"],r)}},{key:"mp4a",value:function(t){var n=t.channelCount,i=t.audioSampleRate,r=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,n,0,16,0,0,0,0,i>>>8&255,255&i,0,0]);return e.box(e.types.mp4a,r,e.esds(t))}},{key:"esds",value:function(t){var n=t.config||[],i=n.length,r=new Uint8Array([0,0,0,0,3,23+i,0,1,0,4,15+i,64,21,0,0,0,0,0,0,0,0,0,0,0,5].concat([i]).concat(n).concat([6,1,2]));return e.box(e.types.esds,r)}},{key:"avc1",value:function(t){var n=t.avcc,i=t.codecWidth,r=t.codecHeight,s=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,i>>>8&255,255&i,r>>>8&255,255&r,0,72,0,0,0,72,0,0,0,0,0,0,0,1,10,120,113,113,47,102,108,118,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,255,255]);return e.box(e.types.avc1,s,e.box(e.types.avcC,n))}},{key:"mvex",value:function(t){return e.box(e.types.mvex,e.trex(t))}},{key:"trex",value:function(t){var n=t.id,i=new Uint8Array([0,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]);return e.box(e.types.trex,i)}},{key:"moof",value:function(t,n){return e.box(e.types.moof,e.mfhd(t.sequenceNumber),e.traf(t,n))}},{key:"mfhd",value:function(t){var n=new Uint8Array([0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t]);return e.box(e.types.mfhd,n)}},{key:"traf",value:function(t,n){var i=t.id,r=e.box(e.types.tfhd,new Uint8Array([0,0,0,0,i>>>24&255,i>>>16&255,i>>>8&255,255&i])),s=e.box(e.types.tfdt,new Uint8Array([0,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n])),a=e.sdtp(t),o=e.trun(t,a.byteLength+16+16+8+16+8+8);return e.box(e.types.traf,r,s,o,a)}},{key:"sdtp",value:function(t){for(var n=t.samples||[],i=n.length,r=new Uint8Array(4+i),s=0;s<i;s++){var a=n[s].flags;r[s+4]=a.isLeading<<6|a.dependsOn<<4|a.isDependedOn<<2|a.hasRedundancy}return e.box(e.types.sdtp,r)}},{key:"trun",value:function(t,n){var i=t.samples||[],r=i.length,s=12+16*r,a=new Uint8Array(s);n+=8+s,a.set([0,0,15,1,r>>>24&255,r>>>16&255,r>>>8&255,255&r,n>>>24&255,n>>>16&255,n>>>8&255,255&n],0);for(var o=0;o<r;o++){var u=i[o].duration,l=i[o].size,d=i[o].flags,h=i[o].cts;a.set([u>>>24&255,u>>>16&255,u>>>8&255,255&u,l>>>24&255,l>>>16&255,l>>>8&255,255&l,d.isLeading<<2|d.dependsOn,d.isDependedOn<<6|d.hasRedundancy<<4|d.isNonSync,0,0,h>>>24&255,h>>>16&255,h>>>8&255,255&h],12+16*o)}return e.box(e.types.trun,a)}},{key:"mdat",value:function(t){return e.box(e.types.mdat,t)}}]),e}();s.init(),n.default=s},{}],38:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("../utils/logger.js"),o=i(a),u=e("./mp4-generator.js"),l=i(u),d=e("./aac-silent.js"),h=i(d),f=e("../utils/browser.js"),c=i(f),_=e("../core/media-segment-info.js"),m=e("../utils/exception.js"),p=function(){function e(t){r(this,e),this.TAG="MP4Remuxer",this._config=t,this._isLive=!0===t.isLive,this._dtsBase=-1,this._dtsBaseInited=!1,this._audioDtsBase=1/0,this._videoDtsBase=1/0,this._audioNextDts=void 0,this._videoNextDts=void 0,this._audioStashedLastSample=null,this._videoStashedLastSample=null,this._audioMeta=null,this._videoMeta=null,this._audioSegmentInfoList=new _.MediaSegmentInfoList("audio"),this._videoSegmentInfoList=new _.MediaSegmentInfoList("video"),this._onInitSegment=null,this._onMediaSegment=null,this._forceFirstIDR=!(!c.default.chrome||!(c.default.version.major<50||50===c.default.version.major&&c.default.version.build<2661)),this._fillSilentAfterSeek=c.default.msedge||c.default.msie,this._mp3UseMpegAudio=!c.default.firefox,this._fillAudioTimestampGap=this._config.fixAudioTimestampGap}return s(e,[{key:"destroy",value:function(){this._dtsBase=-1,this._dtsBaseInited=!1,this._audioMeta=null,this._videoMeta=null,this._audioSegmentInfoList.clear(),this._audioSegmentInfoList=null,this._videoSegmentInfoList.clear(),this._videoSegmentInfoList=null,this._onInitSegment=null,this._onMediaSegment=null}},{key:"bindDataSource",value:function(e){return e.onDataAvailable=this.remux.bind(this),e.onTrackMetadata=this._onTrackMetadataReceived.bind(this),this}},{key:"insertDiscontinuity",value:function(){this._audioNextDts=this._videoNextDts=void 0}},{key:"seek",value:function(e){this._audioStashedLastSample=null,this._videoStashedLastSample=null,this._videoSegmentInfoList.clear(),this._audioSegmentInfoList.clear()}},{key:"remux",value:function(e,t){if(!this._onMediaSegment)throw new m.IllegalStateException("MP4Remuxer: onMediaSegment callback must be specificed!");this._dtsBaseInited||this._calculateDtsBase(e,t),this._remuxVideo(t),this._remuxAudio(e)}},{key:"_onTrackMetadataReceived",value:function(e,t){var n=null,i="mp4",r=t.codec;if("audio"===e)this._audioMeta=t,"mp3"===t.codec&&this._mp3UseMpegAudio?(i="mpeg",r="",n=new Uint8Array):n=l.default.generateInitSegment(t);else{if("video"!==e)return;this._videoMeta=t,n=l.default.generateInitSegment(t)}if(!this._onInitSegment)throw new m.IllegalStateException("MP4Remuxer: onInitSegment callback must be specified!");this._onInitSegment(e,{type:e,data:n.buffer,codec:r,container:e+"/"+i,mediaDuration:t.duration})}},{key:"_calculateDtsBase",value:function(e,t){this._dtsBaseInited||(e.samples&&e.samples.length&&(this._audioDtsBase=e.samples[0].dts),t.samples&&t.samples.length&&(this._videoDtsBase=t.samples[0].dts),this._dtsBase=Math.min(this._audioDtsBase,this._videoDtsBase),this._dtsBaseInited=!0)}},{key:"flushStashedSamples",value:function(){var e=this._videoStashedLastSample,t=this._audioStashedLastSample,n={type:"video",id:1,sequenceNumber:0,samples:[],length:0};null!=e&&(n.samples.push(e),n.length=e.length);var i={type:"audio",id:2,sequenceNumber:0,samples:[],length:0};null!=t&&(i.samples.push(t),i.length=t.length),this._videoStashedLastSample=null,this._audioStashedLastSample=null,this._remuxVideo(n,!0),this._remuxAudio(i,!0)}},{key:"_remuxAudio",value:function(e,t){if(null!=this._audioMeta){var n=e,i=n.samples,r=void 0,s=-1,a=-1,u=this._audioMeta.refSampleDuration,d="mp3"===this._audioMeta.codec&&this._mp3UseMpegAudio,f=this._dtsBaseInited&&void 0===this._audioNextDts,m=!1;if(i&&0!==i.length&&(1!==i.length||t)){var p=0,v=null,g=0;d?(p=0,g=n.length):(p=8,g=8+n.length);var y=null;if(i.length>1&&(y=i.pop(),g-=y.length),null!=this._audioStashedLastSample){var E=this._audioStashedLastSample;this._audioStashedLastSample=null,i.unshift(E),g+=E.length}null!=y&&(this._audioStashedLastSample=y);var b=i[0].dts-this._dtsBase;if(this._audioNextDts)r=b-this._audioNextDts;else if(this._audioSegmentInfoList.isEmpty())r=0,this._fillSilentAfterSeek&&!this._videoSegmentInfoList.isEmpty()&&"mp3"!==this._audioMeta.originalCodec&&(m=!0);else{var S=this._audioSegmentInfoList.getLastSampleBefore(b);if(null!=S){var k=b-(S.originalDts+S.duration);k<=3&&(k=0);var L=S.dts+S.duration+k;r=b-L}else r=0}if(m){var R=b-r,A=this._videoSegmentInfoList.getLastSegmentBefore(b);if(null!=A&&A.beginDts<R){var w=h.default.getSilentFrame(this._audioMeta.originalCodec,this._audioMeta.channelCount);if(w){var T=A.beginDts,O=R-A.beginDts;o.default.v(this.TAG,"InsertPrefixSilentAudio: dts: "+T+", duration: "+O),i.unshift({unit:w,dts:T,pts:T}),g+=w.byteLength}}else m=!1}for(var C=[],I=0;I<i.length;I++){var D=i[I],x=D.unit,M=D.dts-this._dtsBase,B=M-r;-1===s&&(s=B);var j=0;if(I!==i.length-1){j=i[I+1].dts-this._dtsBase-r-B}else if(null!=y){var P=y.dts-this._dtsBase-r;j=P-B}else j=C.length>=1?C[C.length-1].duration:Math.floor(u);var U=!1,N=null;if(j>1.5*u&&"mp3"!==this._audioMeta.codec&&this._fillAudioTimestampGap&&!c.default.safari){U=!0;var F=Math.abs(j-u),G=Math.ceil(F/u),V=B+u;o.default.w(this.TAG,"Large audio timestamp gap detected, may cause AV sync to drift. Silent frames will be generated to avoid unsync.\ndts: "+(B+j)+" ms, expected: "+(B+Math.round(u))+" ms, delta: "+Math.round(F)+" ms, generate: "+G+" frames");var z=h.default.getSilentFrame(this._audioMeta.originalCodec,this._audioMeta.channelCount);null==z&&(o.default.w(this.TAG,"Unable to generate silent frame for "+this._audioMeta.originalCodec+" with "+this._audioMeta.channelCount+" channels, repeat last frame"),z=x),N=[];for(var H=0;H<G;H++){var K=Math.round(V);if(N.length>0){var q=N[N.length-1];q.duration=K-q.dts}var W={dts:K,pts:K,cts:0,unit:z,size:z.byteLength,duration:0,originalDts:M,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0}};N.push(W),g+=W.size,V+=u}var X=N[N.length-1];X.duration=B+j-X.dts,j=Math.round(u)}C.push({dts:B,pts:B,cts:0,unit:D.unit,size:D.unit.byteLength,duration:j,originalDts:M,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0}}),U&&C.push.apply(C,N)}d?v=new Uint8Array(g):(v=new Uint8Array(g),v[0]=g>>>24&255,v[1]=g>>>16&255,v[2]=g>>>8&255,v[3]=255&g,v.set(l.default.types.mdat,4));for(var Y=0;Y<C.length;Y++){var Z=C[Y].unit;v.set(Z,p),p+=Z.byteLength}var Q=C[C.length-1];a=Q.dts+Q.duration,this._audioNextDts=a;var J=new _.MediaSegmentInfo;J.beginDts=s,J.endDts=a,J.beginPts=s,J.endPts=a,J.originalBeginDts=C[0].originalDts,J.originalEndDts=Q.originalDts+Q.duration, | |
| 6 | +J.firstSample=new _.SampleInfo(C[0].dts,C[0].pts,C[0].duration,C[0].originalDts,!1),J.lastSample=new _.SampleInfo(Q.dts,Q.pts,Q.duration,Q.originalDts,!1),this._isLive||this._audioSegmentInfoList.append(J),n.samples=C,n.sequenceNumber++;var $=null;$=d?new Uint8Array:l.default.moof(n,s),n.samples=[],n.length=0;var ee={type:"audio",data:this._mergeBoxes($,v).buffer,sampleCount:C.length,info:J};d&&f&&(ee.timestampOffset=s),this._onMediaSegment("audio",ee)}}}},{key:"_remuxVideo",value:function(e,t){if(null!=this._videoMeta){var n=e,i=n.samples,r=void 0,s=-1,a=-1,o=-1,u=-1;if(i&&0!==i.length&&(1!==i.length||t)){var d=8,h=null,f=8+e.length,c=null;if(i.length>1&&(c=i.pop(),f-=c.length),null!=this._videoStashedLastSample){var m=this._videoStashedLastSample;this._videoStashedLastSample=null,i.unshift(m),f+=m.length}null!=c&&(this._videoStashedLastSample=c);var p=i[0].dts-this._dtsBase;if(this._videoNextDts)r=p-this._videoNextDts;else if(this._videoSegmentInfoList.isEmpty())r=0;else{var v=this._videoSegmentInfoList.getLastSampleBefore(p);if(null!=v){var g=p-(v.originalDts+v.duration);g<=3&&(g=0);var y=v.dts+v.duration+g;r=p-y}else r=0}for(var E=new _.MediaSegmentInfo,b=[],S=0;S<i.length;S++){var k=i[S],L=k.dts-this._dtsBase,R=k.isKeyframe,A=L-r,w=k.cts,T=A+w;-1===s&&(s=A,o=T);var O=0;if(S!==i.length-1){O=i[S+1].dts-this._dtsBase-r-A}else if(null!=c){var C=c.dts-this._dtsBase-r;O=C-A}else O=b.length>=1?b[b.length-1].duration:Math.floor(this._videoMeta.refSampleDuration);if(R){var I=new _.SampleInfo(A,T,O,k.dts,!0);I.fileposition=k.fileposition,E.appendSyncPoint(I)}b.push({dts:A,pts:T,cts:w,units:k.units,size:k.length,isKeyframe:R,duration:O,originalDts:L,flags:{isLeading:0,dependsOn:R?2:1,isDependedOn:R?1:0,hasRedundancy:0,isNonSync:R?0:1}})}h=new Uint8Array(f),h[0]=f>>>24&255,h[1]=f>>>16&255,h[2]=f>>>8&255,h[3]=255&f,h.set(l.default.types.mdat,4);for(var D=0;D<b.length;D++)for(var x=b[D].units;x.length;){var M=x.shift(),B=M.data;h.set(B,d),d+=B.byteLength}var j=b[b.length-1];if(a=j.dts+j.duration,u=j.pts+j.duration,this._videoNextDts=a,E.beginDts=s,E.endDts=a,E.beginPts=o,E.endPts=u,E.originalBeginDts=b[0].originalDts,E.originalEndDts=j.originalDts+j.duration,E.firstSample=new _.SampleInfo(b[0].dts,b[0].pts,b[0].duration,b[0].originalDts,b[0].isKeyframe),E.lastSample=new _.SampleInfo(j.dts,j.pts,j.duration,j.originalDts,j.isKeyframe),this._isLive||this._videoSegmentInfoList.append(E),n.samples=b,n.sequenceNumber++,this._forceFirstIDR){var P=b[0].flags;P.dependsOn=2,P.isNonSync=0}var U=l.default.moof(n,s);n.samples=[],n.length=0,this._onMediaSegment("video",{type:"video",data:this._mergeBoxes(U,h).buffer,sampleCount:b.length,info:E})}}}},{key:"_mergeBoxes",value:function(e,t){var n=new Uint8Array(e.byteLength+t.byteLength);return n.set(e,0),n.set(t,e.byteLength),n}},{key:"onInitSegment",get:function(){return this._onInitSegment},set:function(e){this._onInitSegment=e}},{key:"onMediaSegment",get:function(){return this._onMediaSegment},set:function(e){this._onMediaSegment=e}}]),e}();n.default=p},{"../core/media-segment-info.js":8,"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./aac-silent.js":36,"./mp4-generator.js":37}],39:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={};!function(){var e=self.navigator.userAgent.toLowerCase(),t=/(edge)\/([\w.]+)/.exec(e)||/(opr)[\/]([\w.]+)/.exec(e)||/(chrome)[ \/]([\w.]+)/.exec(e)||/(iemobile)[\/]([\w.]+)/.exec(e)||/(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("trident")>=0&&/(rv)(?::| )([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(firefox)[ \/]([\w.]+)/.exec(e)||[],n=/(ipad)/.exec(e)||/(ipod)/.exec(e)||/(windows phone)/.exec(e)||/(iphone)/.exec(e)||/(kindle)/.exec(e)||/(android)/.exec(e)||/(windows)/.exec(e)||/(mac)/.exec(e)||/(linux)/.exec(e)||/(cros)/.exec(e)||[],r={browser:t[5]||t[3]||t[1]||"",version:t[2]||t[4]||"0",majorVersion:t[4]||t[2]||"0",platform:n[0]||""},s={};if(r.browser){s[r.browser]=!0;var a=r.majorVersion.split(".");s.version={major:parseInt(r.majorVersion,10),string:r.version},a.length>1&&(s.version.minor=parseInt(a[1],10)),a.length>2&&(s.version.build=parseInt(a[2],10))}r.platform&&(s[r.platform]=!0),(s.chrome||s.opr||s.safari)&&(s.webkit=!0),(s.rv||s.iemobile)&&(s.rv&&delete s.rv,r.browser="msie",s.msie=!0),s.edge&&(delete s.edge,r.browser="msedge",s.msedge=!0),s.opr&&(r.browser="opera",s.opera=!0),s.safari&&s.android&&(r.browser="android",s.android=!0),s.name=r.browser,s.platform=r.platform;for(var o in i)i.hasOwnProperty(o)&&delete i[o];Object.assign(i,s)}(),n.default=i},{}],40:[function(e,t,n){"use strict";function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function r(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),o=n.RuntimeException=function(){function e(t){s(this,e),this._message=t}return a(e,[{key:"toString",value:function(){return this.name+": "+this.message}},{key:"name",get:function(){return"RuntimeException"}},{key:"message",get:function(){return this._message}}]),e}();n.IllegalStateException=function(e){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return r(t,e),a(t,[{key:"name",get:function(){return"IllegalStateException"}}]),t}(o),n.InvalidArgumentException=function(e){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return r(t,e),a(t,[{key:"name",get:function(){return"InvalidArgumentException"}}]),t}(o),n.NotImplementedException=function(e){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return r(t,e),a(t,[{key:"name",get:function(){return"NotImplementedException"}}]),t}(o)},{}],41:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("events"),a=function(e){return e&&e.__esModule?e:{default:e}}(s),o=function(){function e(){i(this,e)}return r(e,null,[{key:"e",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","error",i),e.ENABLE_ERROR&&(console.error?console.error(i):console.warn?console.warn(i):console.log(i))}},{key:"i",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","info",i),e.ENABLE_INFO&&(console.info?console.info(i):console.log(i))}},{key:"w",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","warn",i),e.ENABLE_WARN&&(console.warn?console.warn(i):console.log(i))}},{key:"d",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","debug",i),e.ENABLE_DEBUG&&(console.debug?console.debug(i):console.log(i))}},{key:"v",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","verbose",i),e.ENABLE_VERBOSE&&console.log(i)}}]),e}();o.GLOBAL_TAG="flv.js",o.FORCE_GLOBAL_TAG=!1,o.ENABLE_ERROR=!0,o.ENABLE_INFO=!0,o.ENABLE_WARN=!0,o.ENABLE_DEBUG=!0,o.ENABLE_VERBOSE=!0,o.ENABLE_CALLBACK=!1,o.emitter=new a.default,n.default=o},{events:2}],42:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("events"),o=i(a),u=e("./logger.js"),l=i(u),d=function(){function e(){r(this,e)}return s(e,null,[{key:"getConfig",value:function(){return{globalTag:l.default.GLOBAL_TAG,forceGlobalTag:l.default.FORCE_GLOBAL_TAG,enableVerbose:l.default.ENABLE_VERBOSE,enableDebug:l.default.ENABLE_DEBUG,enableInfo:l.default.ENABLE_INFO,enableWarn:l.default.ENABLE_WARN,enableError:l.default.ENABLE_ERROR,enableCallback:l.default.ENABLE_CALLBACK}}},{key:"applyConfig",value:function(e){l.default.GLOBAL_TAG=e.globalTag,l.default.FORCE_GLOBAL_TAG=e.forceGlobalTag,l.default.ENABLE_VERBOSE=e.enableVerbose,l.default.ENABLE_DEBUG=e.enableDebug,l.default.ENABLE_INFO=e.enableInfo,l.default.ENABLE_WARN=e.enableWarn,l.default.ENABLE_ERROR=e.enableError,l.default.ENABLE_CALLBACK=e.enableCallback}},{key:"_notifyChange",value:function(){var t=e.emitter;if(t.listenerCount("change")>0){var n=e.getConfig();t.emit("change",n)}}},{key:"registerListener",value:function(t){e.emitter.addListener("change",t)}},{key:"removeListener",value:function(t){e.emitter.removeListener("change",t)}},{key:"addLogListener",value:function(t){l.default.emitter.addListener("log",t),l.default.emitter.listenerCount("log")>0&&(l.default.ENABLE_CALLBACK=!0,e._notifyChange())}},{key:"removeLogListener",value:function(t){l.default.emitter.removeListener("log",t),0===l.default.emitter.listenerCount("log")&&(l.default.ENABLE_CALLBACK=!1,e._notifyChange())}},{key:"forceGlobalTag",get:function(){return l.default.FORCE_GLOBAL_TAG},set:function(t){l.default.FORCE_GLOBAL_TAG=t,e._notifyChange()}},{key:"globalTag",get:function(){return l.default.GLOBAL_TAG},set:function(t){l.default.GLOBAL_TAG=t,e._notifyChange()}},{key:"enableAll",get:function(){return l.default.ENABLE_VERBOSE&&l.default.ENABLE_DEBUG&&l.default.ENABLE_INFO&&l.default.ENABLE_WARN&&l.default.ENABLE_ERROR},set:function(t){l.default.ENABLE_VERBOSE=t,l.default.ENABLE_DEBUG=t,l.default.ENABLE_INFO=t,l.default.ENABLE_WARN=t,l.default.ENABLE_ERROR=t,e._notifyChange()}},{key:"enableDebug",get:function(){return l.default.ENABLE_DEBUG},set:function(t){l.default.ENABLE_DEBUG=t,e._notifyChange()}},{key:"enableVerbose",get:function(){return l.default.ENABLE_VERBOSE},set:function(t){l.default.ENABLE_VERBOSE=t,e._notifyChange()}},{key:"enableInfo",get:function(){return l.default.ENABLE_INFO},set:function(t){l.default.ENABLE_INFO=t,e._notifyChange()}},{key:"enableWarn",get:function(){return l.default.ENABLE_WARN},set:function(t){l.default.ENABLE_WARN=t,e._notifyChange()}},{key:"enableError",get:function(){return l.default.ENABLE_ERROR},set:function(t){l.default.ENABLE_ERROR=t,e._notifyChange()}}]),e}();d.emitter=new o.default,n.default=d},{"./logger.js":41,events:2}],43:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function t(){i(this,t)}return r(t,null,[{key:"install",value:function(){Object.setPrototypeOf=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},Object.assign=Object.assign||function(e){if(void 0===e||null===e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),n=1;n<arguments.length;n++){var i=arguments[n];if(void 0!==i&&null!==i)for(var r in i)i.hasOwnProperty(r)&&(t[r]=i[r])}return t},"function"!=typeof self.Promise&&e("es6-promise").polyfill()}}]),t}();s.install(),n.default=s},{"es6-promise":1}],44:[function(e,t,n){"use strict";function i(e,t,n){var i=e;if(t+n<i.length){for(;n--;)if(128!=(192&i[++t]))return!1;return!0}return!1}function r(e){for(var t=[],n=e,r=0,s=e.length;r<s;)if(n[r]<128)t.push(String.fromCharCode(n[r])),++r;else{if(n[r]<192);else if(n[r]<224){if(i(n,r,1)){var a=(31&n[r])<<6|63&n[r+1];if(a>=128){t.push(String.fromCharCode(65535&a)),r+=2;continue}}}else if(n[r]<240){if(i(n,r,2)){var o=(15&n[r])<<12|(63&n[r+1])<<6|63&n[r+2];if(o>=2048&&55296!=(63488&o)){t.push(String.fromCharCode(65535&o)),r+=3;continue}}}else if(n[r]<248&&i(n,r,3)){var u=(7&n[r])<<18|(63&n[r+1])<<12|(63&n[r+2])<<6|63&n[r+3];if(u>65536&&u<1114112){u-=65536,t.push(String.fromCharCode(u>>>10|55296)),t.push(String.fromCharCode(1023&u|56320)),r+=4;continue}}t.push(String.fromCharCode(65533)),++r}return t.join("")}Object.defineProperty(n,"__esModule",{value:!0}),n.default=r},{}]},{},[21])(21)}); | |
| 7 | +//# sourceMappingURL=flv.min.js.map | ... | ... |
src/main/resources/g726/in_16.g726
0 → 100644
No preview for this file type
src/main/resources/g726/in_24.g726
0 → 100644
| 1 | --broken encoding: UTF-16BE | ... | ... |
src/main/resources/g726/in_32.g726
0 → 100644
| 1 | --broken encoding: UTF-16BE | ... | ... |
src/main/resources/g726/in_40.g726
0 → 100644
No preview for this file type
src/main/resources/jquery.min.js
0 → 100644
| 1 | +++ a/src/main/resources/jquery.min.js | |
| 1 | +/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ | |
| 2 | +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k}); | ... | ... |
src/main/resources/log4j.properties
0 → 100644
| 1 | +++ a/src/main/resources/log4j.properties | |
| 1 | +platform.name=hentai | |
| 2 | +system.name=video-server | |
| 3 | +log4j.rootLogger = ERROR, Console | |
| 4 | +log4j.appender.Console = org.apache.log4j.ConsoleAppender | |
| 5 | +log4j.appender.Console.layout = org.apache.log4j.PatternLayout | |
| 6 | +log4j.appender.Console.layout.ConversionPattern = [${platform.name}] %d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] [${system.name}] - %c{1} - %m%n | |
| 7 | +log4j.logger.cn.org.hentai = DEBUG | |
| 0 | 8 | \ No newline at end of file | ... | ... |
src/main/resources/multimedia.html
0 → 100644
| 1 | +++ a/src/main/resources/multimedia.html | |
| 1 | +<html> | |
| 2 | +<head> | |
| 3 | + <title>HTTP-Flv Test</title> | |
| 4 | +</head> | |
| 5 | +<body style="background-color: #666666"> | |
| 6 | +<div id="xxoo" style="background-color: #333333;border-radius: 10px; overflow: hidden; width: 400px; height: 300px;"></div> | |
| 7 | +<input id="tag"> | |
| 8 | +<script type="text/javascript"> | |
| 9 | + /*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ | |
| 10 | + !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k}); | |
| 11 | +</script> | |
| 12 | +<script type="text/javascript"> | |
| 13 | + !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.flvjs=e()}}(function(){var e;return function e(t,n,i){function r(a,o){if(!n[a]){if(!t[a]){var u="function"==typeof require&&require;if(!o&&u)return u(a,!0);if(s)return s(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var d=n[a]={exports:{}};t[a][0].call(d.exports,function(e){var n=t[a][1][e];return r(n||e)},d,d.exports,e,t,n,i)}return n[a].exports}for(var s="function"==typeof require&&require,a=0;a<i.length;a++)r(i[a]);return r}({1:[function(t,n,i){(function(r,s){!function(t,r){"object"==typeof i&&void 0!==n?n.exports=r():"function"==typeof e&&e.amd?e(r):t.ES6Promise=r()}(this,function(){"use strict";function e(e){var t=typeof e;return null!==e&&("object"===t||"function"===t)}function n(e){return"function"==typeof e}function i(e){V=e}function a(e){z=e}function o(){return void 0!==G?function(){G(l)}:u()}function u(){var e=setTimeout;return function(){return e(l,1)}}function l(){for(var e=0;e<F;e+=2){(0,Y[e])(Y[e+1]),Y[e]=void 0,Y[e+1]=void 0}F=0}function d(e,t){var n=this,i=new this.constructor(f);void 0===i[Q]&&C(i);var r=n._state;if(r){var s=arguments[r-1];z(function(){return w(r,i,s,n._result)})}else L(n,i,e,t);return i}function h(e){var t=this;if(e&&"object"==typeof e&&e.constructor===t)return e;var n=new t(f);return E(n,e),n}function f(){}function c(){return new TypeError("You cannot resolve a promise with itself")}function _(){return new TypeError("A promises callback cannot return that same promise.")}function m(e){try{return e.then}catch(e){return te.error=e,te}}function p(e,t,n,i){try{e.call(t,n,i)}catch(e){return e}}function v(e,t,n){z(function(e){var i=!1,r=p(n,t,function(n){i||(i=!0,t!==n?E(e,n):S(e,n))},function(t){i||(i=!0,k(e,t))},"Settle: "+(e._label||" unknown promise"));!i&&r&&(i=!0,k(e,r))},e)}function g(e,t){t._state===$?S(e,t._result):t._state===ee?k(e,t._result):L(t,void 0,function(t){return E(e,t)},function(t){return k(e,t)})}function y(e,t,i){t.constructor===e.constructor&&i===d&&t.constructor.resolve===h?g(e,t):i===te?(k(e,te.error),te.error=null):void 0===i?S(e,t):n(i)?v(e,t,i):S(e,t)}function E(t,n){t===n?k(t,c()):e(n)?y(t,n,m(n)):S(t,n)}function b(e){e._onerror&&e._onerror(e._result),R(e)}function S(e,t){e._state===J&&(e._result=t,e._state=$,0!==e._subscribers.length&&z(R,e))}function k(e,t){e._state===J&&(e._state=ee,e._result=t,z(b,e))}function L(e,t,n,i){var r=e._subscribers,s=r.length;e._onerror=null,r[s]=t,r[s+$]=n,r[s+ee]=i,0===s&&e._state&&z(R,e)}function R(e){var t=e._subscribers,n=e._state;if(0!==t.length){for(var i=void 0,r=void 0,s=e._result,a=0;a<t.length;a+=3)i=t[a],r=t[a+n],i?w(n,i,r,s):r(s);e._subscribers.length=0}}function A(e,t){try{return e(t)}catch(e){return te.error=e,te}}function w(e,t,i,r){var s=n(i),a=void 0,o=void 0,u=void 0,l=void 0;if(s){if(a=A(i,r),a===te?(l=!0,o=a.error,a.error=null):u=!0,t===a)return void k(t,_())}else a=r,u=!0;t._state!==J||(s&&u?E(t,a):l?k(t,o):e===$?S(t,a):e===ee&&k(t,a))}function T(e,t){try{t(function(t){E(e,t)},function(t){k(e,t)})}catch(t){k(e,t)}}function O(){return ne++}function C(e){e[Q]=ne++,e._state=void 0,e._result=void 0,e._subscribers=[]}function I(){return new Error("Array Methods must be provided an Array")}function D(e){return new ie(this,e).promise}function x(e){var t=this;return new t(N(e)?function(n,i){for(var r=e.length,s=0;s<r;s++)t.resolve(e[s]).then(n,i)}:function(e,t){return t(new TypeError("You must pass an array to race."))})}function M(e){var t=this,n=new t(f);return k(n,e),n}function B(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function j(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function P(){var e=void 0;if(void 0!==s)e=s;else if("undefined"!=typeof self)e=self;else try{e=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var t=e.Promise;if(t){var n=null;try{n=Object.prototype.toString.call(t.resolve())}catch(e){}if("[object Promise]"===n&&!t.cast)return}e.Promise=re}var U=void 0;U=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var N=U,F=0,G=void 0,V=void 0,z=function(e,t){Y[F]=e,Y[F+1]=t,2===(F+=2)&&(V?V(l):Z())},H="undefined"!=typeof window?window:void 0,K=H||{},q=K.MutationObserver||K.WebKitMutationObserver,W="undefined"==typeof self&&void 0!==r&&"[object process]"==={}.toString.call(r),X="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,Y=new Array(1e3),Z=void 0;Z=W?function(){return function(){return r.nextTick(l)}}():q?function(){var e=0,t=new q(l),n=document.createTextNode("");return t.observe(n,{characterData:!0}),function(){n.data=e=++e%2}}():X?function(){var e=new MessageChannel;return e.port1.onmessage=l,function(){return e.port2.postMessage(0)}}():void 0===H&&"function"==typeof t?function(){try{var e=Function("return this")().require("vertx");return G=e.runOnLoop||e.runOnContext,o()}catch(e){return u()}}():u();var Q=Math.random().toString(36).substring(2),J=void 0,$=1,ee=2,te={error:null},ne=0,ie=function(){function e(e,t){this._instanceConstructor=e,this.promise=new e(f),this.promise[Q]||C(this.promise),N(t)?(this.length=t.length,this._remaining=t.length,this._result=new Array(this.length),0===this.length?S(this.promise,this._result):(this.length=this.length||0,this._enumerate(t),0===this._remaining&&S(this.promise,this._result))):k(this.promise,I())}return e.prototype._enumerate=function(e){for(var t=0;this._state===J&&t<e.length;t++)this._eachEntry(e[t],t)},e.prototype._eachEntry=function(e,t){var n=this._instanceConstructor,i=n.resolve;if(i===h){var r=m(e);if(r===d&&e._state!==J)this._settledAt(e._state,t,e._result);else if("function"!=typeof r)this._remaining--,this._result[t]=e;else if(n===re){var s=new n(f);y(s,e,r),this._willSettleAt(s,t)}else this._willSettleAt(new n(function(t){return t(e)}),t)}else this._willSettleAt(i(e),t)},e.prototype._settledAt=function(e,t,n){var i=this.promise;i._state===J&&(this._remaining--,e===ee?k(i,n):this._result[t]=n),0===this._remaining&&S(i,this._result)},e.prototype._willSettleAt=function(e,t){var n=this;L(e,void 0,function(e){return n._settledAt($,t,e)},function(e){return n._settledAt(ee,t,e)})},e}(),re=function(){function e(t){this[Q]=O(),this._result=this._state=void 0,this._subscribers=[],f!==t&&("function"!=typeof t&&B(),this instanceof e?T(this,t):j())}return e.prototype.catch=function(e){return this.then(null,e)},e.prototype.finally=function(e){var t=this,i=t.constructor;return n(e)?t.then(function(t){return i.resolve(e()).then(function(){return t})},function(t){return i.resolve(e()).then(function(){throw t})}):t.then(e,e)},e}();return re.prototype.then=d,re.all=D,re.race=x,re.resolve=h,re.reject=M,re._setScheduler=i,re._setAsap=a,re._asap=z,re.polyfill=P,re.Promise=re,re})}).call(this,t("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:3}],2:[function(e,t,n){function i(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return"function"==typeof e}function s(e){return"number"==typeof e}function a(e){return"object"==typeof e&&null!==e}function o(e){return void 0===e}t.exports=i,i.EventEmitter=i,i.prototype._events=void 0,i.prototype._maxListeners=void 0,i.defaultMaxListeners=10,i.prototype.setMaxListeners=function(e){if(!s(e)||e<0||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},i.prototype.emit=function(e){var t,n,i,s,u,l;if(this._events||(this._events={}),"error"===e&&(!this._events.error||a(this._events.error)&&!this._events.error.length)){if((t=arguments[1])instanceof Error)throw t;var d=new Error('Uncaught, unspecified "error" event. ('+t+")");throw d.context=t,d}if(n=this._events[e],o(n))return!1;if(r(n))switch(arguments.length){case 1:n.call(this);break;case 2:n.call(this,arguments[1]);break;case 3:n.call(this,arguments[1],arguments[2]);break;default:s=Array.prototype.slice.call(arguments,1),n.apply(this,s)}else if(a(n))for(s=Array.prototype.slice.call(arguments,1),l=n.slice(),i=l.length,u=0;u<i;u++)l[u].apply(this,s);return!0},i.prototype.addListener=function(e,t){var n;if(!r(t))throw TypeError("listener must be a function");return this._events||(this._events={}),this._events.newListener&&this.emit("newListener",e,r(t.listener)?t.listener:t),this._events[e]?a(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t,a(this._events[e])&&!this._events[e].warned&&(n=o(this._maxListeners)?i.defaultMaxListeners:this._maxListeners)&&n>0&&this._events[e].length>n&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace()),this},i.prototype.on=i.prototype.addListener,i.prototype.once=function(e,t){function n(){this.removeListener(e,n),i||(i=!0,t.apply(this,arguments))}if(!r(t))throw TypeError("listener must be a function");var i=!1;return n.listener=t,this.on(e,n),this},i.prototype.removeListener=function(e,t){var n,i,s,o;if(!r(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(n=this._events[e],s=n.length,i=-1,n===t||r(n.listener)&&n.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(a(n)){for(o=s;o-- >0;)if(n[o]===t||n[o].listener&&n[o].listener===t){i=o;break}if(i<0)return this;1===n.length?(n.length=0,delete this._events[e]):n.splice(i,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},i.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(n=this._events[e],r(n))this.removeListener(e,n);else if(n)for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},i.prototype.listeners=function(e){return this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},i.prototype.listenerCount=function(e){if(this._events){var t=this._events[e];if(r(t))return 1;if(t)return t.length}return 0},i.listenerCount=function(e,t){return e.listenerCount(t)}},{}],3:[function(e,t,n){function i(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function s(e){if(h===setTimeout)return setTimeout(e,0);if((h===i||!h)&&setTimeout)return h=setTimeout,setTimeout(e,0);try{return h(e,0)}catch(t){try{return h.call(null,e,0)}catch(t){return h.call(this,e,0)}}}function a(e){if(f===clearTimeout)return clearTimeout(e);if((f===r||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(e);try{return f(e)}catch(t){try{return f.call(null,e)}catch(t){return f.call(this,e)}}}function o(){p&&_&&(p=!1,_.length?m=_.concat(m):v=-1,m.length&&u())}function u(){if(!p){var e=s(o);p=!0;for(var t=m.length;t;){for(_=m,m=[];++v<t;)_&&_[v].run();v=-1,t=m.length}_=null,p=!1,a(e)}}function l(e,t){this.fun=e,this.array=t}function d(){}var h,f,c=t.exports={};!function(){try{h="function"==typeof setTimeout?setTimeout:i}catch(e){h=i}try{f="function"==typeof clearTimeout?clearTimeout:r}catch(e){f=r}}();var _,m=[],p=!1,v=-1;c.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];m.push(new l(e,t)),1!==m.length||p||s(u)},l.prototype.run=function(){this.fun.apply(null,this.array)},c.title="browser",c.browser=!0,c.env={},c.argv=[],c.version="",c.versions={},c.on=d,c.addListener=d,c.once=d,c.off=d,c.removeListener=d,c.removeAllListeners=d,c.emit=d,c.prependListener=d,c.prependOnceListener=d,c.listeners=function(e){return[]},c.binding=function(e){throw new Error("process.binding is not supported")},c.cwd=function(){return"/"},c.chdir=function(e){throw new Error("process.chdir is not supported")},c.umask=function(){return 0}},{}],4:[function(e,t,n){var i=arguments[3],r=arguments[4],s=arguments[5],a=JSON.stringify;t.exports=function(e,t){function n(e){p[e]=!0;for(var t in r[e][1]){var i=r[e][1][t];p[i]||n(i)}}for(var o,u=Object.keys(s),l=0,d=u.length;l<d;l++){var h=u[l],f=s[h].exports;if(f===e||f&&f.default===e){o=h;break}}if(!o){o=Math.floor(Math.pow(16,8)*Math.random()).toString(16);for(var c={},l=0,d=u.length;l<d;l++){var h=u[l];c[h]=h}r[o]=["function(require,module,exports){"+e+"(self); }",c]}var _=Math.floor(Math.pow(16,8)*Math.random()).toString(16),m={};m[o]=o,r[_]=["function(require,module,exports){var f = require("+a(o)+");(f.default ? f.default : f)(self);}",m];var p={};n(_);var v="("+i+")({"+Object.keys(p).map(function(e){return a(e)+":["+r[e][0]+","+a(r[e][1])+"]"}).join(",")+"},{},["+a(_)+"])",g=window.URL||window.webkitURL||window.mozURL||window.msURL,y=new Blob([v],{type:"text/javascript"});if(t&&t.bare)return y;var E=g.createObjectURL(y),b=new Worker(E);return b.objectURL=E,b}},{}],5:[function(e,t,n){"use strict";function i(){return Object.assign({},r)}Object.defineProperty(n,"__esModule",{value:!0}),n.createDefaultConfig=i;var r=n.defaultConfig={enableWorker:!1,enableStashBuffer:!0,stashInitialSize:void 0,isLive:!1,lazyLoad:!0,lazyLoadMaxDuration:180,lazyLoadRecoverDuration:30,deferLoadAfterSourceOpen:!0,autoCleanupMaxBackwardDuration:180,autoCleanupMinBackwardDuration:120,statisticsInfoReportInterval:600,fixAudioTimestampGap:!0,accurateSeek:!1,seekType:"range",seekParamStart:"bstart",seekParamEnd:"bend",rangeLoadZeroStart:!1,customSeekHandler:void 0,reuseRedirectedURL:!1,headers:void 0,customLoader:void 0}},{}],6:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("../io/io-controller.js"),a=function(e){return e&&e.__esModule?e:{default:e}}(s),o=e("../config.js"),u=function(){function e(){i(this,e)}return r(e,null,[{key:"supportMSEH264Playback",value:function(){return window.MediaSource&&window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"')}},{key:"supportNetworkStreamIO",value:function(){var e=new a.default({},(0,o.createDefaultConfig)()),t=e.loaderType;return e.destroy(),"fetch-stream-loader"==t||"xhr-moz-chunked-loader"==t}},{key:"getNetworkLoaderTypeName",value:function(){var e=new a.default({},(0,o.createDefaultConfig)()),t=e.loaderType;return e.destroy(),t}},{key:"supportNativeMediaPlayback",value:function(t){void 0==e.videoElement&&(e.videoElement=window.document.createElement("video"));var n=e.videoElement.canPlayType(t);return"probably"===n||"maybe"==n}},{key:"getFeatureList",value:function(){var t={mseFlvPlayback:!1,mseLiveFlvPlayback:!1,networkStreamIO:!1,networkLoaderName:"",nativeMP4H264Playback:!1,nativeWebmVP8Playback:!1,nativeWebmVP9Playback:!1};return t.mseFlvPlayback=e.supportMSEH264Playback(),t.networkStreamIO=e.supportNetworkStreamIO(),t.networkLoaderName=e.getNetworkLoaderTypeName(),t.mseLiveFlvPlayback=t.mseFlvPlayback&&t.networkStreamIO,t.nativeMP4H264Playback=e.supportNativeMediaPlayback('video/mp4; codecs="avc1.42001E, mp4a.40.2"'),t.nativeWebmVP8Playback=e.supportNativeMediaPlayback('video/webm; codecs="vp8.0, vorbis"'),t.nativeWebmVP9Playback=e.supportNativeMediaPlayback('video/webm; codecs="vp9"'),t}}]),e}();n.default=u},{"../config.js":5,"../io/io-controller.js":23}],7:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(){i(this,e),this.mimeType=null,this.duration=null,this.hasAudio=null,this.hasVideo=null,this.audioCodec=null,this.videoCodec=null,this.audioDataRate=null,this.videoDataRate=null,this.audioSampleRate=null,this.audioChannelCount=null,this.width=null,this.height=null,this.fps=null,this.profile=null,this.level=null,this.refFrames=null,this.chromaFormat=null,this.sarNum=null,this.sarDen=null,this.metadata=null,this.segments=null,this.segmentCount=null,this.hasKeyframesIndex=null,this.keyframesIndex=null}return r(e,[{key:"isComplete",value:function(){var e=!1===this.hasAudio||!0===this.hasAudio&&null!=this.audioCodec&&null!=this.audioSampleRate&&null!=this.audioChannelCount,t=!1===this.hasVideo||!0===this.hasVideo&&null!=this.videoCodec&&null!=this.width&&null!=this.height&&null!=this.fps&&null!=this.profile&&null!=this.level&&null!=this.refFrames&&null!=this.chromaFormat&&null!=this.sarNum&&null!=this.sarDen;return null!=this.mimeType&&null!=this.duration&&null!=this.metadata&&null!=this.hasKeyframesIndex&&e&&t}},{key:"isSeekable",value:function(){return!0===this.hasKeyframesIndex}},{key:"getNearestKeyframe",value:function(e){if(null==this.keyframesIndex)return null;var t=this.keyframesIndex,n=this._search(t.times,e);return{index:n,milliseconds:t.times[n],fileposition:t.filepositions[n]}}},{key:"_search",value:function(e,t){var n=0,i=e.length-1,r=0,s=0,a=i;for(t<e[0]&&(n=0,s=a+1);s<=a;){if((r=s+Math.floor((a-s)/2))===i||t>=e[r]&&t<e[r+1]){n=r;break}e[r]<t?s=r+1:a=r-1}return n}}]),e}();n.default=s},{}],8:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();n.SampleInfo=function e(t,n,r,s,a){i(this,e),this.dts=t,this.pts=n,this.duration=r,this.originalDts=s,this.isSyncPoint=a,this.fileposition=null},n.MediaSegmentInfo=function(){function e(){i(this,e),this.beginDts=0,this.endDts=0,this.beginPts=0,this.endPts=0,this.originalBeginDts=0,this.originalEndDts=0,this.syncPoints=[],this.firstSample=null,this.lastSample=null}return r(e,[{key:"appendSyncPoint",value:function(e){e.isSyncPoint=!0,this.syncPoints.push(e)}}]),e}(),n.IDRSampleList=function(){function e(){i(this,e),this._list=[]}return r(e,[{key:"clear",value:function(){this._list=[]}},{key:"appendArray",value:function(e){var t=this._list;0!==e.length&&(t.length>0&&e[0].originalDts<t[t.length-1].originalDts&&this.clear(),Array.prototype.push.apply(t,e))}},{key:"getLastSyncPointBeforeDts",value:function(e){if(0==this._list.length)return null;var t=this._list,n=0,i=t.length-1,r=0,s=0,a=i;for(e<t[0].dts&&(n=0,s=a+1);s<=a;){if((r=s+Math.floor((a-s)/2))===i||e>=t[r].dts&&e<t[r+1].dts){n=r;break}t[r].dts<e?s=r+1:a=r-1}return this._list[n]}}]),e}(),n.MediaSegmentInfoList=function(){function e(t){i(this,e),this._type=t,this._list=[],this._lastAppendLocation=-1}return r(e,[{key:"isEmpty",value:function(){return 0===this._list.length}},{key:"clear",value:function(){this._list=[],this._lastAppendLocation=-1}},{key:"_searchNearestSegmentBefore",value:function(e){var t=this._list;if(0===t.length)return-2;var n=t.length-1,i=0,r=0,s=n,a=0;if(e<t[0].originalBeginDts)return a=-1;for(;r<=s;){if((i=r+Math.floor((s-r)/2))===n||e>t[i].lastSample.originalDts&&e<t[i+1].originalBeginDts){a=i;break}t[i].originalBeginDts<e?r=i+1:s=i-1}return a}},{key:"_searchNearestSegmentAfter",value:function(e){return this._searchNearestSegmentBefore(e)+1}},{key:"append",value:function(e){var t=this._list,n=e,i=this._lastAppendLocation,r=0;-1!==i&&i<t.length&&n.originalBeginDts>=t[i].lastSample.originalDts&&(i===t.length-1||i<t.length-1&&n.originalBeginDts<t[i+1].originalBeginDts)?r=i+1:t.length>0&&(r=this._searchNearestSegmentBefore(n.originalBeginDts)+1),this._lastAppendLocation=r,this._list.splice(r,0,n)}},{key:"getLastSegmentBefore",value:function(e){var t=this._searchNearestSegmentBefore(e);return t>=0?this._list[t]:null}},{key:"getLastSampleBefore",value:function(e){var t=this.getLastSegmentBefore(e);return null!=t?t.lastSample:null}},{key:"getLastSyncPointBefore",value:function(e){for(var t=this._searchNearestSegmentBefore(e),n=this._list[t].syncPoints;0===n.length&&t>0;)t--,n=this._list[t].syncPoints;return n.length>0?n[n.length-1]:null}},{key:"type",get:function(){return this._type}},{key:"length",get:function(){return this._list.length}}]),e}()},{}],9:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("events"),o=i(a),u=e("../utils/logger.js"),l=i(u),d=e("../utils/browser.js"),h=i(d),f=e("./mse-events.js"),c=i(f),_=e("./media-segment-info.js"),m=e("../utils/exception.js"),p=function(){function e(t){r(this,e),this.TAG="MSEController",this._config=t,this._emitter=new o.default,this._config.isLive&&void 0==this._config.autoCleanupSourceBuffer&&(this._config.autoCleanupSourceBuffer=!0),this.e={onSourceOpen:this._onSourceOpen.bind(this),onSourceEnded:this._onSourceEnded.bind(this),onSourceClose:this._onSourceClose.bind(this),onSourceBufferError:this._onSourceBufferError.bind(this),onSourceBufferUpdateEnd:this._onSourceBufferUpdateEnd.bind(this)},this._mediaSource=null,this._mediaSourceObjectURL=null,this._mediaElement=null,this._isBufferFull=!1,this._hasPendingEos=!1,this._requireSetMediaDuration=!1,this._pendingMediaDuration=0,this._pendingSourceBufferInit=[],this._mimeTypes={video:null,audio:null},this._sourceBuffers={video:null,audio:null},this._lastInitSegments={video:null,audio:null},this._pendingSegments={video:[],audio:[]},this._pendingRemoveRanges={video:[],audio:[]},this._idrList=new _.IDRSampleList}return s(e,[{key:"destroy",value:function(){(this._mediaElement||this._mediaSource)&&this.detachMediaElement(),this.e=null,this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{key:"attachMediaElement",value:function(e){if(this._mediaSource)throw new m.IllegalStateException("MediaSource has been attached to an HTMLMediaElement!");var t=this._mediaSource=new window.MediaSource;t.addEventListener("sourceopen",this.e.onSourceOpen),t.addEventListener("sourceended",this.e.onSourceEnded),t.addEventListener("sourceclose",this.e.onSourceClose),this._mediaElement=e,this._mediaSourceObjectURL=window.URL.createObjectURL(this._mediaSource),e.src=this._mediaSourceObjectURL}},{key:"detachMediaElement",value:function(){if(this._mediaSource){var e=this._mediaSource;for(var t in this._sourceBuffers){var n=this._pendingSegments[t];n.splice(0,n.length),this._pendingSegments[t]=null,this._pendingRemoveRanges[t]=null,this._lastInitSegments[t]=null;var i=this._sourceBuffers[t];if(i){if("closed"!==e.readyState){try{e.removeSourceBuffer(i)}catch(e){l.default.e(this.TAG,e.message)}i.removeEventListener("error",this.e.onSourceBufferError),i.removeEventListener("updateend",this.e.onSourceBufferUpdateEnd)}this._mimeTypes[t]=null,this._sourceBuffers[t]=null}}if("open"===e.readyState)try{e.endOfStream()}catch(e){l.default.e(this.TAG,e.message)}e.removeEventListener("sourceopen",this.e.onSourceOpen),e.removeEventListener("sourceended",this.e.onSourceEnded),e.removeEventListener("sourceclose",this.e.onSourceClose),this._pendingSourceBufferInit=[],this._isBufferFull=!1,this._idrList.clear(),this._mediaSource=null}this._mediaElement&&(this._mediaElement.src="",this._mediaElement.removeAttribute("src"),this._mediaElement=null),this._mediaSourceObjectURL&&(window.URL.revokeObjectURL(this._mediaSourceObjectURL),this._mediaSourceObjectURL=null)}},{key:"appendInitSegment",value:function(e,t){if(!this._mediaSource||"open"!==this._mediaSource.readyState)return this._pendingSourceBufferInit.push(e),void this._pendingSegments[e.type].push(e);var n=e,i=""+n.container;n.codec&&n.codec.length>0&&(i+=";codecs="+n.codec);var r=!1;if(l.default.v(this.TAG,"Received Initialization Segment, mimeType: "+i),this._lastInitSegments[n.type]=n,i!==this._mimeTypes[n.type]){if(this._mimeTypes[n.type])l.default.v(this.TAG,"Notice: "+n.type+" mimeType changed, origin: "+this._mimeTypes[n.type]+", target: "+i);else{r=!0;try{var s=this._sourceBuffers[n.type]=this._mediaSource.addSourceBuffer(i);s.addEventListener("error",this.e.onSourceBufferError),s.addEventListener("updateend",this.e.onSourceBufferUpdateEnd)}catch(e){return l.default.e(this.TAG,e.message),void this._emitter.emit(c.default.ERROR,{code:e.code,msg:e.message})}}this._mimeTypes[n.type]=i}t||this._pendingSegments[n.type].push(n),r||this._sourceBuffers[n.type]&&!this._sourceBuffers[n.type].updating&&this._doAppendSegments(),h.default.safari&&"audio/mpeg"===n.container&&n.mediaDuration>0&&(this._requireSetMediaDuration=!0,this._pendingMediaDuration=n.mediaDuration/1e3,this._updateMediaSourceDuration())}},{key:"appendMediaSegment",value:function(e){var t=e;this._pendingSegments[t.type].push(t),this._config.autoCleanupSourceBuffer&&this._needCleanupSourceBuffer()&&this._doCleanupSourceBuffer();var n=this._sourceBuffers[t.type];!n||n.updating||this._hasPendingRemoveRanges()||this._doAppendSegments()}},{key:"seek",value:function(e){for(var t in this._sourceBuffers)if(this._sourceBuffers[t]){var n=this._sourceBuffers[t];if("open"===this._mediaSource.readyState)try{n.abort()}catch(e){l.default.e(this.TAG,e.message)}this._idrList.clear();var i=this._pendingSegments[t];if(i.splice(0,i.length),"closed"!==this._mediaSource.readyState){for(var r=0;r<n.buffered.length;r++){var s=n.buffered.start(r),a=n.buffered.end(r);this._pendingRemoveRanges[t].push({start:s,end:a})}if(n.updating||this._doRemoveRanges(),h.default.safari){var o=this._lastInitSegments[t];o&&(this._pendingSegments[t].push(o),n.updating||this._doAppendSegments())}}}}},{key:"endOfStream",value:function(){var e=this._mediaSource,t=this._sourceBuffers;if(!e||"open"!==e.readyState)return void(e&&"closed"===e.readyState&&this._hasPendingSegments()&&(this._hasPendingEos=!0));t.video&&t.video.updating||t.audio&&t.audio.updating?this._hasPendingEos=!0:(this._hasPendingEos=!1,e.endOfStream())}},{key:"getNearestKeyframe",value:function(e){return this._idrList.getLastSyncPointBeforeDts(e)}},{key:"_needCleanupSourceBuffer",value:function(){if(!this._config.autoCleanupSourceBuffer)return!1;var e=this._mediaElement.currentTime;for(var t in this._sourceBuffers){var n=this._sourceBuffers[t];if(n){var i=n.buffered;if(i.length>=1&&e-i.start(0)>=this._config.autoCleanupMaxBackwardDuration)return!0}}return!1}},{key:"_doCleanupSourceBuffer",value:function(){var e=this._mediaElement.currentTime;for(var t in this._sourceBuffers){var n=this._sourceBuffers[t];if(n){for(var i=n.buffered,r=!1,s=0;s<i.length;s++){var a=i.start(s),o=i.end(s);if(a<=e&&e<o+3){if(e-a>=this._config.autoCleanupMaxBackwardDuration){r=!0;var u=e-this._config.autoCleanupMinBackwardDuration;this._pendingRemoveRanges[t].push({start:a,end:u})}}else o<e&&(r=!0,this._pendingRemoveRanges[t].push({start:a,end:o}))}r&&!n.updating&&this._doRemoveRanges()}}}},{key:"_updateMediaSourceDuration",value:function(){var e=this._sourceBuffers;if(0!==this._mediaElement.readyState&&"open"===this._mediaSource.readyState&&!(e.video&&e.video.updating||e.audio&&e.audio.updating)){var t=this._mediaSource.duration,n=this._pendingMediaDuration;n>0&&(isNaN(t)||n>t)&&(l.default.v(this.TAG,"Update MediaSource duration from "+t+" to "+n),this._mediaSource.duration=n),this._requireSetMediaDuration=!1,this._pendingMediaDuration=0}}},{key:"_doRemoveRanges",value:function(){for(var e in this._pendingRemoveRanges)if(this._sourceBuffers[e]&&!this._sourceBuffers[e].updating)for(var t=this._sourceBuffers[e],n=this._pendingRemoveRanges[e];n.length&&!t.updating;){var i=n.shift();t.remove(i.start,i.end)}}},{key:"_doAppendSegments",value:function(){var e=this._pendingSegments;for(var t in e)if(this._sourceBuffers[t]&&!this._sourceBuffers[t].updating&&e[t].length>0){var n=e[t].shift();if(n.timestampOffset){var i=this._sourceBuffers[t].timestampOffset,r=n.timestampOffset/1e3,s=Math.abs(i-r);s>.1&&(l.default.v(this.TAG,"Update MPEG audio timestampOffset from "+i+" to "+r),this._sourceBuffers[t].timestampOffset=r),delete n.timestampOffset}if(!n.data||0===n.data.byteLength)continue;try{this._sourceBuffers[t].appendBuffer(n.data),this._isBufferFull=!1,"video"===t&&n.hasOwnProperty("info")&&this._idrList.appendArray(n.info.syncPoints)}catch(e){this._pendingSegments[t].unshift(n),22===e.code?(this._isBufferFull||this._emitter.emit(c.default.BUFFER_FULL),this._isBufferFull=!0):(l.default.e(this.TAG,e.message),this._emitter.emit(c.default.ERROR,{code:e.code,msg:e.message}))}}}},{key:"_onSourceOpen",value:function(){if(l.default.v(this.TAG,"MediaSource onSourceOpen"),this._mediaSource.removeEventListener("sourceopen",this.e.onSourceOpen),this._pendingSourceBufferInit.length>0)for(var e=this._pendingSourceBufferInit;e.length;){var t=e.shift();this.appendInitSegment(t,!0)}this._hasPendingSegments()&&this._doAppendSegments(),this._emitter.emit(c.default.SOURCE_OPEN)}},{key:"_onSourceEnded",value:function(){l.default.v(this.TAG,"MediaSource onSourceEnded")}},{key:"_onSourceClose",value:function(){l.default.v(this.TAG,"MediaSource onSourceClose"),this._mediaSource&&null!=this.e&&(this._mediaSource.removeEventListener("sourceopen",this.e.onSourceOpen),this._mediaSource.removeEventListener("sourceended",this.e.onSourceEnded),this._mediaSource.removeEventListener("sourceclose",this.e.onSourceClose))}},{key:"_hasPendingSegments",value:function(){var e=this._pendingSegments;return e.video.length>0||e.audio.length>0}},{key:"_hasPendingRemoveRanges",value:function(){var e=this._pendingRemoveRanges;return e.video.length>0||e.audio.length>0}},{key:"_onSourceBufferUpdateEnd",value:function(){this._requireSetMediaDuration?this._updateMediaSourceDuration():this._hasPendingRemoveRanges()?this._doRemoveRanges():this._hasPendingSegments()?this._doAppendSegments():this._hasPendingEos&&this.endOfStream(),this._emitter.emit(c.default.UPDATE_END)}},{key:"_onSourceBufferError",value:function(e){l.default.e(this.TAG,"SourceBuffer Error: "+e)}}]),e}();n.default=p},{"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./media-segment-info.js":8,"./mse-events.js":10,events:2}],10:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={ERROR:"error",SOURCE_OPEN:"source_open",UPDATE_END:"update_end",BUFFER_FULL:"buffer_full"};n.default=i},{}],11:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){ | |
| 14 | + function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("events"),o=i(a),u=e("../utils/logger.js"),l=i(u),d=e("../utils/logging-control.js"),h=i(d),f=e("./transmuxing-controller.js"),c=i(f),_=e("./transmuxing-events.js"),m=i(_),p=e("./transmuxing-worker.js"),v=i(p),g=e("./media-info.js"),y=i(g),E=function(){function t(n,i){if(r(this,t),this.TAG="Transmuxer",this._emitter=new o.default,i.enableWorker&&"undefined"!=typeof Worker)try{var s=e("webworkify");this._worker=s(v.default),this._workerDestroying=!1,this._worker.addEventListener("message",this._onWorkerMessage.bind(this)),this._worker.postMessage({cmd:"init",param:[n,i]}),this.e={onLoggingConfigChanged:this._onLoggingConfigChanged.bind(this)},h.default.registerListener(this.e.onLoggingConfigChanged),this._worker.postMessage({cmd:"logging_config",param:h.default.getConfig()})}catch(e){l.default.e(this.TAG,"Error while initialize transmuxing worker, fallback to inline transmuxing"),this._worker=null,this._controller=new c.default(n,i)}else this._controller=new c.default(n,i);if(this._controller){var a=this._controller;a.on(m.default.IO_ERROR,this._onIOError.bind(this)),a.on(m.default.DEMUX_ERROR,this._onDemuxError.bind(this)),a.on(m.default.INIT_SEGMENT,this._onInitSegment.bind(this)),a.on(m.default.MEDIA_SEGMENT,this._onMediaSegment.bind(this)),a.on(m.default.LOADING_COMPLETE,this._onLoadingComplete.bind(this)),a.on(m.default.RECOVERED_EARLY_EOF,this._onRecoveredEarlyEof.bind(this)),a.on(m.default.MEDIA_INFO,this._onMediaInfo.bind(this)),a.on(m.default.METADATA_ARRIVED,this._onMetaDataArrived.bind(this)),a.on(m.default.SCRIPTDATA_ARRIVED,this._onScriptDataArrived.bind(this)),a.on(m.default.STATISTICS_INFO,this._onStatisticsInfo.bind(this)),a.on(m.default.RECOMMEND_SEEKPOINT,this._onRecommendSeekpoint.bind(this))}}return s(t,[{key:"destroy",value:function(){this._worker?this._workerDestroying||(this._workerDestroying=!0,this._worker.postMessage({cmd:"destroy"}),h.default.removeListener(this.e.onLoggingConfigChanged),this.e=null):(this._controller.destroy(),this._controller=null),this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{key:"hasWorker",value:function(){return null!=this._worker}},{key:"open",value:function(){this._worker?this._worker.postMessage({cmd:"start"}):this._controller.start()}},{key:"close",value:function(){this._worker?this._worker.postMessage({cmd:"stop"}):this._controller.stop()}},{key:"seek",value:function(e){this._worker?this._worker.postMessage({cmd:"seek",param:e}):this._controller.seek(e)}},{key:"pause",value:function(){this._worker?this._worker.postMessage({cmd:"pause"}):this._controller.pause()}},{key:"resume",value:function(){this._worker?this._worker.postMessage({cmd:"resume"}):this._controller.resume()}},{key:"_onInitSegment",value:function(e,t){var n=this;Promise.resolve().then(function(){n._emitter.emit(m.default.INIT_SEGMENT,e,t)})}},{key:"_onMediaSegment",value:function(e,t){var n=this;Promise.resolve().then(function(){n._emitter.emit(m.default.MEDIA_SEGMENT,e,t)})}},{key:"_onLoadingComplete",value:function(){var e=this;Promise.resolve().then(function(){e._emitter.emit(m.default.LOADING_COMPLETE)})}},{key:"_onRecoveredEarlyEof",value:function(){var e=this;Promise.resolve().then(function(){e._emitter.emit(m.default.RECOVERED_EARLY_EOF)})}},{key:"_onMediaInfo",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.MEDIA_INFO,e)})}},{key:"_onMetaDataArrived",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.METADATA_ARRIVED,e)})}},{key:"_onScriptDataArrived",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.SCRIPTDATA_ARRIVED,e)})}},{key:"_onStatisticsInfo",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.STATISTICS_INFO,e)})}},{key:"_onIOError",value:function(e,t){var n=this;Promise.resolve().then(function(){n._emitter.emit(m.default.IO_ERROR,e,t)})}},{key:"_onDemuxError",value:function(e,t){var n=this;Promise.resolve().then(function(){n._emitter.emit(m.default.DEMUX_ERROR,e,t)})}},{key:"_onRecommendSeekpoint",value:function(e){var t=this;Promise.resolve().then(function(){t._emitter.emit(m.default.RECOMMEND_SEEKPOINT,e)})}},{key:"_onLoggingConfigChanged",value:function(e){this._worker&&this._worker.postMessage({cmd:"logging_config",param:e})}},{key:"_onWorkerMessage",value:function(e){var t=e.data,n=t.data;if("destroyed"===t.msg||this._workerDestroying)return this._workerDestroying=!1,this._worker.terminate(),void(this._worker=null);switch(t.msg){case m.default.INIT_SEGMENT:case m.default.MEDIA_SEGMENT:this._emitter.emit(t.msg,n.type,n.data);break;case m.default.LOADING_COMPLETE:case m.default.RECOVERED_EARLY_EOF:this._emitter.emit(t.msg);break;case m.default.MEDIA_INFO:Object.setPrototypeOf(n,y.default.prototype),this._emitter.emit(t.msg,n);break;case m.default.METADATA_ARRIVED:case m.default.SCRIPTDATA_ARRIVED:case m.default.STATISTICS_INFO:this._emitter.emit(t.msg,n);break;case m.default.IO_ERROR:case m.default.DEMUX_ERROR:this._emitter.emit(t.msg,n.type,n.info);break;case m.default.RECOMMEND_SEEKPOINT:this._emitter.emit(t.msg,n);break;case"logcat_callback":l.default.emitter.emit("log",n.type,n.logcat)}}}]),t}();n.default=E},{"../utils/logger.js":41,"../utils/logging-control.js":42,"./media-info.js":7,"./transmuxing-controller.js":12,"./transmuxing-events.js":13,"./transmuxing-worker.js":14,events:2,webworkify:4}],12:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("events"),o=i(a),u=e("../utils/logger.js"),l=i(u),d=e("../utils/browser.js"),h=i(d),f=e("./media-info.js"),c=i(f),_=e("../demux/flv-demuxer.js"),m=i(_),p=e("../remux/mp4-remuxer.js"),v=i(p),g=e("../demux/demux-errors.js"),y=i(g),E=e("../io/io-controller.js"),b=i(E),S=e("./transmuxing-events.js"),k=i(S),L=(e("../io/loader.js"),function(){function e(t,n){r(this,e),this.TAG="TransmuxingController",this._emitter=new o.default,this._config=n,t.segments||(t.segments=[{duration:t.duration,filesize:t.filesize,url:t.url}]),"boolean"!=typeof t.cors&&(t.cors=!0),"boolean"!=typeof t.withCredentials&&(t.withCredentials=!1),this._mediaDataSource=t,this._currentSegmentIndex=0;var i=0;this._mediaDataSource.segments.forEach(function(e){e.timestampBase=i,i+=e.duration,e.cors=t.cors,e.withCredentials=t.withCredentials,n.referrerPolicy&&(e.referrerPolicy=n.referrerPolicy)}),isNaN(i)||this._mediaDataSource.duration===i||(this._mediaDataSource.duration=i),this._mediaInfo=null,this._demuxer=null,this._remuxer=null,this._ioctl=null,this._pendingSeekTime=null,this._pendingResolveSeekPoint=null,this._statisticsReporter=null}return s(e,[{key:"destroy",value:function(){this._mediaInfo=null,this._mediaDataSource=null,this._statisticsReporter&&this._disableStatisticsReporter(),this._ioctl&&(this._ioctl.destroy(),this._ioctl=null),this._demuxer&&(this._demuxer.destroy(),this._demuxer=null),this._remuxer&&(this._remuxer.destroy(),this._remuxer=null),this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{key:"start",value:function(){this._loadSegment(0),this._enableStatisticsReporter()}},{key:"_loadSegment",value:function(e,t){this._currentSegmentIndex=e;var n=this._mediaDataSource.segments[e],i=this._ioctl=new b.default(n,this._config,e);i.onError=this._onIOException.bind(this),i.onSeeked=this._onIOSeeked.bind(this),i.onComplete=this._onIOComplete.bind(this),i.onRedirect=this._onIORedirect.bind(this),i.onRecoveredEarlyEof=this._onIORecoveredEarlyEof.bind(this),t?this._demuxer.bindDataSource(this._ioctl):i.onDataArrival=this._onInitChunkArrival.bind(this),i.open(t)}},{key:"stop",value:function(){this._internalAbort(),this._disableStatisticsReporter()}},{key:"_internalAbort",value:function(){this._ioctl&&(this._ioctl.destroy(),this._ioctl=null)}},{key:"pause",value:function(){this._ioctl&&this._ioctl.isWorking()&&(this._ioctl.pause(),this._disableStatisticsReporter())}},{key:"resume",value:function(){this._ioctl&&this._ioctl.isPaused()&&(this._ioctl.resume(),this._enableStatisticsReporter())}},{key:"seek",value:function(e){if(null!=this._mediaInfo&&this._mediaInfo.isSeekable()){var t=this._searchSegmentIndexContains(e);if(t===this._currentSegmentIndex){var n=this._mediaInfo.segments[t];if(void 0==n)this._pendingSeekTime=e;else{var i=n.getNearestKeyframe(e);this._remuxer.seek(i.milliseconds),this._ioctl.seek(i.fileposition),this._pendingResolveSeekPoint=i.milliseconds}}else{var r=this._mediaInfo.segments[t];if(void 0==r)this._pendingSeekTime=e,this._internalAbort(),this._remuxer.seek(),this._remuxer.insertDiscontinuity(),this._loadSegment(t);else{var s=r.getNearestKeyframe(e);this._internalAbort(),this._remuxer.seek(e),this._remuxer.insertDiscontinuity(),this._demuxer.resetMediaInfo(),this._demuxer.timestampBase=this._mediaDataSource.segments[t].timestampBase,this._loadSegment(t,s.fileposition),this._pendingResolveSeekPoint=s.milliseconds,this._reportSegmentMediaInfo(t)}}this._enableStatisticsReporter()}}},{key:"_searchSegmentIndexContains",value:function(e){for(var t=this._mediaDataSource.segments,n=t.length-1,i=0;i<t.length;i++)if(e<t[i].timestampBase){n=i-1;break}return n}},{key:"_onInitChunkArrival",value:function(e,t){var n=this,i=null,r=0;if(t>0)this._demuxer.bindDataSource(this._ioctl),this._demuxer.timestampBase=this._mediaDataSource.segments[this._currentSegmentIndex].timestampBase,r=this._demuxer.parseChunks(e,t);else if((i=m.default.probe(e)).match){this._demuxer=new m.default(i,this._config),this._remuxer||(this._remuxer=new v.default(this._config));var s=this._mediaDataSource;void 0==s.duration||isNaN(s.duration)||(this._demuxer.overridedDuration=s.duration),"boolean"==typeof s.hasAudio&&(this._demuxer.overridedHasAudio=s.hasAudio),"boolean"==typeof s.hasVideo&&(this._demuxer.overridedHasVideo=s.hasVideo),this._demuxer.timestampBase=s.segments[this._currentSegmentIndex].timestampBase,this._demuxer.onError=this._onDemuxException.bind(this),this._demuxer.onMediaInfo=this._onMediaInfo.bind(this),this._demuxer.onMetaDataArrived=this._onMetaDataArrived.bind(this),this._demuxer.onScriptDataArrived=this._onScriptDataArrived.bind(this),this._remuxer.bindDataSource(this._demuxer.bindDataSource(this._ioctl)),this._remuxer.onInitSegment=this._onRemuxerInitSegmentArrival.bind(this),this._remuxer.onMediaSegment=this._onRemuxerMediaSegmentArrival.bind(this),r=this._demuxer.parseChunks(e,t)}else i=null,l.default.e(this.TAG,"Non-FLV, Unsupported media type!"),Promise.resolve().then(function(){n._internalAbort()}),this._emitter.emit(k.default.DEMUX_ERROR,y.default.FORMAT_UNSUPPORTED,"Non-FLV, Unsupported media type"),r=0;return r}},{key:"_onMediaInfo",value:function(e){var t=this;null==this._mediaInfo&&(this._mediaInfo=Object.assign({},e),this._mediaInfo.keyframesIndex=null,this._mediaInfo.segments=[],this._mediaInfo.segmentCount=this._mediaDataSource.segments.length,Object.setPrototypeOf(this._mediaInfo,c.default.prototype));var n=Object.assign({},e);Object.setPrototypeOf(n,c.default.prototype),this._mediaInfo.segments[this._currentSegmentIndex]=n,this._reportSegmentMediaInfo(this._currentSegmentIndex),null!=this._pendingSeekTime&&Promise.resolve().then(function(){var e=t._pendingSeekTime;t._pendingSeekTime=null,t.seek(e)})}},{key:"_onMetaDataArrived",value:function(e){this._emitter.emit(k.default.METADATA_ARRIVED,e)}},{key:"_onScriptDataArrived",value:function(e){this._emitter.emit(k.default.SCRIPTDATA_ARRIVED,e)}},{key:"_onIOSeeked",value:function(){this._remuxer.insertDiscontinuity()}},{key:"_onIOComplete",value:function(e){var t=e,n=t+1;n<this._mediaDataSource.segments.length?(this._internalAbort(),this._remuxer.flushStashedSamples(),this._loadSegment(n)):(this._remuxer.flushStashedSamples(),this._emitter.emit(k.default.LOADING_COMPLETE),this._disableStatisticsReporter())}},{key:"_onIORedirect",value:function(e){var t=this._ioctl.extraData;this._mediaDataSource.segments[t].redirectedURL=e}},{key:"_onIORecoveredEarlyEof",value:function(){this._emitter.emit(k.default.RECOVERED_EARLY_EOF)}},{key:"_onIOException",value:function(e,t){l.default.e(this.TAG,"IOException: type = "+e+", code = "+t.code+", msg = "+t.msg),this._emitter.emit(k.default.IO_ERROR,e,t),this._disableStatisticsReporter()}},{key:"_onDemuxException",value:function(e,t){l.default.e(this.TAG,"DemuxException: type = "+e+", info = "+t),this._emitter.emit(k.default.DEMUX_ERROR,e,t)}},{key:"_onRemuxerInitSegmentArrival",value:function(e,t){this._emitter.emit(k.default.INIT_SEGMENT,e,t)}},{key:"_onRemuxerMediaSegmentArrival",value:function(e,t){if(null==this._pendingSeekTime&&(this._emitter.emit(k.default.MEDIA_SEGMENT,e,t),null!=this._pendingResolveSeekPoint&&"video"===e)){var n=t.info.syncPoints,i=this._pendingResolveSeekPoint;this._pendingResolveSeekPoint=null,h.default.safari&&n.length>0&&n[0].originalDts===i&&(i=n[0].pts),this._emitter.emit(k.default.RECOMMEND_SEEKPOINT,i)}}},{key:"_enableStatisticsReporter",value:function(){null==this._statisticsReporter&&(this._statisticsReporter=self.setInterval(this._reportStatisticsInfo.bind(this),this._config.statisticsInfoReportInterval))}},{key:"_disableStatisticsReporter",value:function(){this._statisticsReporter&&(self.clearInterval(this._statisticsReporter),this._statisticsReporter=null)}},{key:"_reportSegmentMediaInfo",value:function(e){var t=this._mediaInfo.segments[e],n=Object.assign({},t);n.duration=this._mediaInfo.duration,n.segmentCount=this._mediaInfo.segmentCount,delete n.segments,delete n.keyframesIndex,this._emitter.emit(k.default.MEDIA_INFO,n)}},{key:"_reportStatisticsInfo",value:function(){var e={};e.url=this._ioctl.currentURL,e.hasRedirect=this._ioctl.hasRedirect,e.hasRedirect&&(e.redirectedURL=this._ioctl.currentRedirectedURL),e.speed=this._ioctl.currentSpeed,e.loaderType=this._ioctl.loaderType,e.currentSegmentIndex=this._currentSegmentIndex,e.totalSegmentCount=this._mediaDataSource.segments.length,this._emitter.emit(k.default.STATISTICS_INFO,e)}}]),e}());n.default=L},{"../demux/demux-errors.js":16,"../demux/flv-demuxer.js":18,"../io/io-controller.js":23,"../io/loader.js":24,"../remux/mp4-remuxer.js":38,"../utils/browser.js":39,"../utils/logger.js":41,"./media-info.js":7,"./transmuxing-events.js":13,events:2}],13:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={IO_ERROR:"io_error",DEMUX_ERROR:"demux_error",INIT_SEGMENT:"init_segment",MEDIA_SEGMENT:"media_segment",LOADING_COMPLETE:"loading_complete",RECOVERED_EARLY_EOF:"recovered_early_eof",MEDIA_INFO:"media_info",METADATA_ARRIVED:"metadata_arrived",SCRIPTDATA_ARRIVED:"scriptdata_arrived",STATISTICS_INFO:"statistics_info",RECOMMEND_SEEKPOINT:"recommend_seekpoint"};n.default=i},{}],14:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(n,"__esModule",{value:!0});var r=e("../utils/logger.js"),s=(i(r),e("../utils/logging-control.js")),a=i(s),o=e("../utils/polyfill.js"),u=i(o),l=e("./transmuxing-controller.js"),d=i(l),h=e("./transmuxing-events.js"),f=i(h),c=function(e){function t(t,n){var i={msg:f.default.INIT_SEGMENT,data:{type:t,data:n}};e.postMessage(i,[n.data])}function n(t,n){var i={msg:f.default.MEDIA_SEGMENT,data:{type:t,data:n}};e.postMessage(i,[n.data])}function i(){var t={msg:f.default.LOADING_COMPLETE};e.postMessage(t)}function r(){var t={msg:f.default.RECOVERED_EARLY_EOF};e.postMessage(t)}function s(t){var n={msg:f.default.MEDIA_INFO,data:t};e.postMessage(n)}function o(t){var n={msg:f.default.METADATA_ARRIVED,data:t};e.postMessage(n)}function l(t){var n={msg:f.default.SCRIPTDATA_ARRIVED,data:t};e.postMessage(n)}function h(t){var n={msg:f.default.STATISTICS_INFO,data:t};e.postMessage(n)}function c(t,n){e.postMessage({msg:f.default.IO_ERROR,data:{type:t,info:n}})}function _(t,n){e.postMessage({msg:f.default.DEMUX_ERROR,data:{type:t,info:n}})}function m(t){e.postMessage({msg:f.default.RECOMMEND_SEEKPOINT,data:t})}function p(t,n){e.postMessage({msg:"logcat_callback",data:{type:t,logcat:n}})}var v=null,g=p.bind(this);u.default.install(),e.addEventListener("message",function(u){switch(u.data.cmd){case"init":v=new d.default(u.data.param[0],u.data.param[1]),v.on(f.default.IO_ERROR,c.bind(this)),v.on(f.default.DEMUX_ERROR,_.bind(this)),v.on(f.default.INIT_SEGMENT,t.bind(this)),v.on(f.default.MEDIA_SEGMENT,n.bind(this)),v.on(f.default.LOADING_COMPLETE,i.bind(this)),v.on(f.default.RECOVERED_EARLY_EOF,r.bind(this)),v.on(f.default.MEDIA_INFO,s.bind(this)),v.on(f.default.METADATA_ARRIVED,o.bind(this)),v.on(f.default.SCRIPTDATA_ARRIVED,l.bind(this)),v.on(f.default.STATISTICS_INFO,h.bind(this)),v.on(f.default.RECOMMEND_SEEKPOINT,m.bind(this));break;case"destroy":v&&(v.destroy(),v=null),e.postMessage({msg:"destroyed"});break;case"start":v.start();break;case"stop":v.stop();break;case"seek":v.seek(u.data.param);break;case"pause":v.pause();break;case"resume":v.resume();break;case"logging_config":var p=u.data.param;a.default.applyConfig(p),!0===p.enableCallback?a.default.addLogListener(g):a.default.removeLogListener(g)}})};n.default=c},{"../utils/logger.js":41,"../utils/logging-control.js":42,"../utils/polyfill.js":43,"./transmuxing-controller.js":12,"./transmuxing-events.js":13}],15:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("../utils/logger.js"),o=i(a),u=e("../utils/utf8-conv.js"),l=i(u),d=e("../utils/exception.js"),h=function(){var e=new ArrayBuffer(2);return new DataView(e).setInt16(0,256,!0),256===new Int16Array(e)[0]}(),f=function(){function e(){r(this,e)}return s(e,null,[{key:"parseScriptData",value:function(t,n,i){var r={};try{var s=e.parseValue(t,n,i),a=e.parseValue(t,n+s.size,i-s.size);r[s.data]=a.data}catch(e){o.default.e("AMF",e.toString())}return r}},{key:"parseObject",value:function(t,n,i){if(i<3)throw new d.IllegalStateException("Data not enough when parse ScriptDataObject");var r=e.parseString(t,n,i),s=e.parseValue(t,n+r.size,i-r.size),a=s.objectEnd;return{data:{name:r.data,value:s.data},size:r.size+s.size,objectEnd:a}}},{key:"parseVariable",value:function(t,n,i){return e.parseObject(t,n,i)}},{key:"parseString",value:function(e,t,n){if(n<2)throw new d.IllegalStateException("Data not enough when parse String");var i=new DataView(e,t,n),r=i.getUint16(0,!h),s=void 0;return s=r>0?(0,l.default)(new Uint8Array(e,t+2,r)):"",{data:s,size:2+r}}},{key:"parseLongString",value:function(e,t,n){if(n<4)throw new d.IllegalStateException("Data not enough when parse LongString");var i=new DataView(e,t,n),r=i.getUint32(0,!h),s=void 0;return s=r>0?(0,l.default)(new Uint8Array(e,t+4,r)):"",{data:s,size:4+r}}},{key:"parseDate",value:function(e,t,n){if(n<10)throw new d.IllegalStateException("Data size invalid when parse Date");var i=new DataView(e,t,n),r=i.getFloat64(0,!h);return r+=60*i.getInt16(8,!h)*1e3,{data:new Date(r),size:10}}},{key:"parseValue",value:function(t,n,i){if(i<1)throw new d.IllegalStateException("Data not enough when parse Value");var r=new DataView(t,n,i),s=1,a=r.getUint8(0),u=void 0,l=!1;try{switch(a){case 0:u=r.getFloat64(1,!h),s+=8;break;case 1:u=!!r.getUint8(1),s+=1;break;case 2:var f=e.parseString(t,n+1,i-1);u=f.data,s+=f.size;break;case 3:u={};var c=0;for(9==(16777215&r.getUint32(i-4,!h))&&(c=3);s<i-4;){var _=e.parseObject(t,n+s,i-s-c);if(_.objectEnd)break;u[_.data.name]=_.data.value,s+=_.size}if(s<=i-3){9===(16777215&r.getUint32(s-1,!h))&&(s+=3)}break;case 8:u={},s+=4;var m=0;for(9==(16777215&r.getUint32(i-4,!h))&&(m=3);s<i-8;){var p=e.parseVariable(t,n+s,i-s-m);if(p.objectEnd)break;u[p.data.name]=p.data.value,s+=p.size}if(s<=i-3){9===(16777215&r.getUint32(s-1,!h))&&(s+=3)}break;case 9:u=void 0,s=1,l=!0;break;case 10:u=[];var v=r.getUint32(1,!h);s+=4;for(var g=0;g<v;g++){var y=e.parseValue(t,n+s,i-s);u.push(y.data),s+=y.size}break;case 11:var E=e.parseDate(t,n+1,i-1);u=E.data,s+=E.size;break;case 12:var b=e.parseString(t,n+1,i-1);u=b.data,s+=b.size;break;default:s=i,o.default.w("AMF","Unsupported AMF value type "+a)}}catch(e){o.default.e("AMF",e.toString())}return{data:u,size:s,objectEnd:l}}}]),e}();n.default=f},{"../utils/exception.js":40,"../utils/logger.js":41,"../utils/utf8-conv.js":44}],16:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={OK:"OK",FORMAT_ERROR:"FormatError",FORMAT_UNSUPPORTED:"FormatUnsupported",CODEC_UNSUPPORTED:"CodecUnsupported"};n.default=i},{}],17:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("../utils/exception.js"),a=function(){function e(t){i(this,e),this.TAG="ExpGolomb",this._buffer=t,this._buffer_index=0,this._total_bytes=t.byteLength,this._total_bits=8*t.byteLength,this._current_word=0,this._current_word_bits_left=0}return r(e,[{key:"destroy",value:function(){this._buffer=null}},{key:"_fillCurrentWord",value:function(){var e=this._total_bytes-this._buffer_index;if(e<=0)throw new s.IllegalStateException("ExpGolomb: _fillCurrentWord() but no bytes available");var t=Math.min(4,e),n=new Uint8Array(4);n.set(this._buffer.subarray(this._buffer_index,this._buffer_index+t)),this._current_word=new DataView(n.buffer).getUint32(0,!1),this._buffer_index+=t,this._current_word_bits_left=8*t}},{key:"readBits",value:function(e){if(e>32)throw new s.InvalidArgumentException("ExpGolomb: readBits() bits exceeded max 32bits!");if(e<=this._current_word_bits_left){var t=this._current_word>>>32-e;return this._current_word<<=e,this._current_word_bits_left-=e,t}var n=this._current_word_bits_left?this._current_word:0;n>>>=32-this._current_word_bits_left;var i=e-this._current_word_bits_left;this._fillCurrentWord();var r=Math.min(i,this._current_word_bits_left),a=this._current_word>>>32-r;return this._current_word<<=r,this._current_word_bits_left-=r,n=n<<r|a}},{key:"readBool",value:function(){return 1===this.readBits(1)}},{key:"readByte",value:function(){return this.readBits(8)}},{key:"_skipLeadingZero",value:function(){var e=void 0;for(e=0;e<this._current_word_bits_left;e++)if(0!=(this._current_word&2147483648>>>e))return this._current_word<<=e,this._current_word_bits_left-=e,e;return this._fillCurrentWord(),e+this._skipLeadingZero()}},{key:"readUEG",value:function(){var e=this._skipLeadingZero();return this.readBits(e+1)-1}},{key:"readSEG",value:function(){var e=this.readUEG();return 1&e?e+1>>>1:-1*(e>>>1)}}]),e}();n.default=a},{"../utils/exception.js":40}],18:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){return e[t]<<24|e[t+1]<<16|e[t+2]<<8|e[t+3]}Object.defineProperty(n,"__esModule",{value:!0});var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),u=e("../utils/logger.js"),l=i(u),d=e("./amf-parser.js"),h=i(d),f=e("./sps-parser.js"),c=i(f),_=e("./demux-errors.js"),m=i(_),p=e("../core/media-info.js"),v=i(p),g=e("../utils/exception.js"),y=function(){function e(t,n){r(this,e),this.TAG="FLVDemuxer",this._config=n,this._onError=null,this._onMediaInfo=null,this._onMetaDataArrived=null,this._onScriptDataArrived=null,this._onTrackMetadata=null,this._onDataAvailable=null,this._dataOffset=t.dataOffset,this._firstParse=!0,this._dispatch=!1,this._hasAudio=t.hasAudioTrack,this._hasVideo=t.hasVideoTrack,this._hasAudioFlagOverrided=!1,this._hasVideoFlagOverrided=!1,this._audioInitialMetadataDispatched=!1,this._videoInitialMetadataDispatched=!1,this._mediaInfo=new v.default,this._mediaInfo.hasAudio=this._hasAudio,this._mediaInfo.hasVideo=this._hasVideo,this._metadata=null,this._audioMetadata=null,this._videoMetadata=null,this._naluLengthSize=4,this._timestampBase=0,this._timescale=1e3,this._duration=0,this._durationOverrided=!1,this._referenceFrameRate={fixed:!0,fps:23.976,fps_num:23976,fps_den:1e3},this._flvSoundRateTable=[5500,11025,22050,44100,48e3],this._mpegSamplingRates=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],this._mpegAudioV10SampleRateTable=[44100,48e3,32e3,0],this._mpegAudioV20SampleRateTable=[22050,24e3,16e3,0],this._mpegAudioV25SampleRateTable=[11025,12e3,8e3,0],this._mpegAudioL1BitRateTable=[0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,-1],this._mpegAudioL2BitRateTable=[0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,-1],this._mpegAudioL3BitRateTable=[0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,-1],this._videoTrack={type:"video",id:1,sequenceNumber:0,samples:[],length:0},this._audioTrack={type:"audio",id:2,sequenceNumber:0,samples:[],length:0},this._littleEndian=function(){var e=new ArrayBuffer(2);return new DataView(e).setInt16(0,256,!0),256===new Int16Array(e)[0]}()}return o(e,[{key:"destroy",value:function(){this._mediaInfo=null,this._metadata=null,this._audioMetadata=null,this._videoMetadata=null,this._videoTrack=null,this._audioTrack=null,this._onError=null,this._onMediaInfo=null,this._onMetaDataArrived=null,this._onScriptDataArrived=null,this._onTrackMetadata=null,this._onDataAvailable=null}},{key:"bindDataSource",value:function(e){return e.onDataArrival=this.parseChunks.bind(this),this}},{key:"resetMediaInfo",value:function(){this._mediaInfo=new v.default}},{key:"_isInitialMetadataDispatched",value:function(){return this._hasAudio&&this._hasVideo?this._audioInitialMetadataDispatched&&this._videoInitialMetadataDispatched:this._hasAudio&&!this._hasVideo?this._audioInitialMetadataDispatched:!(this._hasAudio||!this._hasVideo)&&this._videoInitialMetadataDispatched}},{key:"parseChunks",value:function(t,n){if(!(this._onError&&this._onMediaInfo&&this._onTrackMetadata&&this._onDataAvailable))throw new g.IllegalStateException("Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified");var i=0,r=this._littleEndian;if(0===n){if(!(t.byteLength>13))return 0;i=e.probe(t).dataOffset}if(this._firstParse){this._firstParse=!1,n+i!==this._dataOffset&&l.default.w(this.TAG,"First time parsing but chunk byteStart invalid!");0!==new DataView(t,i).getUint32(0,!r)&&l.default.w(this.TAG,"PrevTagSize0 !== 0 !!!"),i+=4}for(;i<t.byteLength;){this._dispatch=!0;var s=new DataView(t,i);if(i+11+4>t.byteLength)break;var a=s.getUint8(0),o=16777215&s.getUint32(0,!r);if(i+11+o+4>t.byteLength)break;if(8===a||9===a||18===a){var u=s.getUint8(4),d=s.getUint8(5),h=s.getUint8(6),f=s.getUint8(7),c=h|d<<8|u<<16|f<<24;0!==(16777215&s.getUint32(7,!r))&&l.default.w(this.TAG,"Meet tag which has StreamID != 0!");var _=i+11;switch(a){case 8:this._parseAudioData(t,_,o,c);break;case 9:this._parseVideoData(t,_,o,c,n+i);break;case 18:this._parseScriptData(t,_,o)}var m=s.getUint32(11+o,!r);m!==11+o&&l.default.w(this.TAG,"Invalid PrevTagSize "+m),i+=11+o+4}else l.default.w(this.TAG,"Unsupported tag type "+a+", skipped"),i+=11+o+4}return this._isInitialMetadataDispatched()&&this._dispatch&&(this._audioTrack.length||this._videoTrack.length)&&this._onDataAvailable(this._audioTrack,this._videoTrack),i}},{key:"_parseScriptData",value:function(e,t,n){var i=h.default.parseScriptData(e,t,n);if(i.hasOwnProperty("onMetaData")){if(null==i.onMetaData||"object"!==a(i.onMetaData))return void l.default.w(this.TAG,"Invalid onMetaData structure!");this._metadata&&l.default.w(this.TAG,"Found another onMetaData tag!"),this._metadata=i;var r=this._metadata.onMetaData;if(this._onMetaDataArrived&&this._onMetaDataArrived(Object.assign({},r)),"boolean"==typeof r.hasAudio&&!1===this._hasAudioFlagOverrided&&(this._hasAudio=r.hasAudio,this._mediaInfo.hasAudio=this._hasAudio),"boolean"==typeof r.hasVideo&&!1===this._hasVideoFlagOverrided&&(this._hasVideo=r.hasVideo,this._mediaInfo.hasVideo=this._hasVideo),"number"==typeof r.audiodatarate&&(this._mediaInfo.audioDataRate=r.audiodatarate),"number"==typeof r.videodatarate&&(this._mediaInfo.videoDataRate=r.videodatarate),"number"==typeof r.width&&(this._mediaInfo.width=r.width),"number"==typeof r.height&&(this._mediaInfo.height=r.height),"number"==typeof r.duration){if(!this._durationOverrided){var s=Math.floor(r.duration*this._timescale);this._duration=s,this._mediaInfo.duration=s}}else this._mediaInfo.duration=0;if("number"==typeof r.framerate){var o=Math.floor(1e3*r.framerate);if(o>0){var u=o/1e3;this._referenceFrameRate.fixed=!0,this._referenceFrameRate.fps=u,this._referenceFrameRate.fps_num=o,this._referenceFrameRate.fps_den=1e3,this._mediaInfo.fps=u}}if("object"===a(r.keyframes)){this._mediaInfo.hasKeyframesIndex=!0;var d=r.keyframes;this._mediaInfo.keyframesIndex=this._parseKeyframesIndex(d),r.keyframes=null}else this._mediaInfo.hasKeyframesIndex=!1;this._dispatch=!1,this._mediaInfo.metadata=r,l.default.v(this.TAG,"Parsed onMetaData"),this._mediaInfo.isComplete()&&this._onMediaInfo(this._mediaInfo)}Object.keys(i).length>0&&this._onScriptDataArrived&&this._onScriptDataArrived(Object.assign({},i))}},{key:"_parseKeyframesIndex",value:function(e){for(var t=[],n=[],i=1;i<e.times.length;i++){var r=this._timestampBase+Math.floor(1e3*e.times[i]);t.push(r),n.push(e.filepositions[i])}return{times:t,filepositions:n}}},{key:"_parseAudioData",value:function(e,t,n,i){if(n<=1)return void l.default.w(this.TAG,"Flv: Invalid audio packet, missing SoundData payload!");if(!0!==this._hasAudioFlagOverrided||!1!==this._hasAudio){var r=(this._littleEndian,new DataView(e,t,n)),s=r.getUint8(0),a=s>>>4;if(2!==a&&10!==a)return void this._onError(m.default.CODEC_UNSUPPORTED,"Flv: Unsupported audio codec idx: "+a);var o=0,u=(12&s)>>>2;if(!(u>=0&&u<=4))return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid audio sample rate idx: "+u);o=this._flvSoundRateTable[u];var d=1&s,h=this._audioMetadata,f=this._audioTrack;if(h||(!1===this._hasAudio&&!1===this._hasAudioFlagOverrided&&(this._hasAudio=!0,this._mediaInfo.hasAudio=!0),h=this._audioMetadata={},h.type="audio",h.id=f.id,h.timescale=this._timescale,h.duration=this._duration,h.audioSampleRate=o,h.channelCount=0===d?1:2),10===a){var c=this._parseAACAudioData(e,t+1,n-1);if(void 0==c)return;if(0===c.packetType){h.config&&l.default.w(this.TAG,"Found another AudioSpecificConfig!");var _=c.data;h.audioSampleRate=_.samplingRate,h.channelCount=_.channelCount,h.codec=_.codec,h.originalCodec=_.originalCodec,h.config=_.config, | |
| 15 | + h.refSampleDuration=1024/h.audioSampleRate*h.timescale,l.default.v(this.TAG,"Parsed AudioSpecificConfig"),this._isInitialMetadataDispatched()?this._dispatch&&(this._audioTrack.length||this._videoTrack.length)&&this._onDataAvailable(this._audioTrack,this._videoTrack):this._audioInitialMetadataDispatched=!0,this._dispatch=!1,this._onTrackMetadata("audio",h);var p=this._mediaInfo;p.audioCodec=h.originalCodec,p.audioSampleRate=h.audioSampleRate,p.audioChannelCount=h.channelCount,p.hasVideo?null!=p.videoCodec&&(p.mimeType='video/x-flv; codecs="'+p.videoCodec+","+p.audioCodec+'"'):p.mimeType='video/x-flv; codecs="'+p.audioCodec+'"',p.isComplete()&&this._onMediaInfo(p)}else if(1===c.packetType){var v=this._timestampBase+i,g={unit:c.data,length:c.data.byteLength,dts:v,pts:v};f.samples.push(g),f.length+=c.data.length}else l.default.e(this.TAG,"Flv: Unsupported AAC data type "+c.packetType)}else if(2===a){if(!h.codec){var y=this._parseMP3AudioData(e,t+1,n-1,!0);if(void 0==y)return;h.audioSampleRate=y.samplingRate,h.channelCount=y.channelCount,h.codec=y.codec,h.originalCodec=y.originalCodec,h.refSampleDuration=1152/h.audioSampleRate*h.timescale,l.default.v(this.TAG,"Parsed MPEG Audio Frame Header"),this._audioInitialMetadataDispatched=!0,this._onTrackMetadata("audio",h);var E=this._mediaInfo;E.audioCodec=h.codec,E.audioSampleRate=h.audioSampleRate,E.audioChannelCount=h.channelCount,E.audioDataRate=y.bitRate,E.hasVideo?null!=E.videoCodec&&(E.mimeType='video/x-flv; codecs="'+E.videoCodec+","+E.audioCodec+'"'):E.mimeType='video/x-flv; codecs="'+E.audioCodec+'"',E.isComplete()&&this._onMediaInfo(E)}var b=this._parseMP3AudioData(e,t+1,n-1,!1);if(void 0==b)return;var S=this._timestampBase+i,k={unit:b,length:b.byteLength,dts:S,pts:S};f.samples.push(k),f.length+=b.length}}}},{key:"_parseAACAudioData",value:function(e,t,n){if(n<=1)return void l.default.w(this.TAG,"Flv: Invalid AAC packet, missing AACPacketType or/and Data!");var i={},r=new Uint8Array(e,t,n);return i.packetType=r[0],0===r[0]?i.data=this._parseAACAudioSpecificConfig(e,t+1,n-1):i.data=r.subarray(1),i}},{key:"_parseAACAudioSpecificConfig",value:function(e,t,n){var i=new Uint8Array(e,t,n),r=null,s=0,a=0,o=0,u=null;if(s=a=i[0]>>>3,(o=(7&i[0])<<1|i[1]>>>7)<0||o>=this._mpegSamplingRates.length)return void this._onError(m.default.FORMAT_ERROR,"Flv: AAC invalid sampling frequency index!");var l=this._mpegSamplingRates[o],d=(120&i[1])>>>3;if(d<0||d>=8)return void this._onError(m.default.FORMAT_ERROR,"Flv: AAC invalid channel configuration");5===s&&(u=(7&i[1])<<1|i[2]>>>7,i[2]);var h=self.navigator.userAgent.toLowerCase();return-1!==h.indexOf("firefox")?o>=6?(s=5,r=new Array(4),u=o-3):(s=2,r=new Array(2),u=o):-1!==h.indexOf("android")?(s=2,r=new Array(2),u=o):(s=5,u=o,r=new Array(4),o>=6?u=o-3:1===d&&(s=2,r=new Array(2),u=o)),r[0]=s<<3,r[0]|=(15&o)>>>1,r[1]=(15&o)<<7,r[1]|=(15&d)<<3,5===s&&(r[1]|=(15&u)>>>1,r[2]=(1&u)<<7,r[2]|=8,r[3]=0),{config:r,samplingRate:l,channelCount:d,codec:"mp4a.40."+s,originalCodec:"mp4a.40."+a}}},{key:"_parseMP3AudioData",value:function(e,t,n,i){if(n<4)return void l.default.w(this.TAG,"Flv: Invalid MP3 packet, header missing!");var r=(this._littleEndian,new Uint8Array(e,t,n)),s=null;if(i){if(255!==r[0])return;var a=r[1]>>>3&3,o=(6&r[1])>>1,u=(240&r[2])>>>4,d=(12&r[2])>>>2,h=r[3]>>>6&3,f=3!==h?2:1,c=0,_=0;switch(a){case 0:c=this._mpegAudioV25SampleRateTable[d];break;case 2:c=this._mpegAudioV20SampleRateTable[d];break;case 3:c=this._mpegAudioV10SampleRateTable[d]}switch(o){case 1:34,u<this._mpegAudioL3BitRateTable.length&&(_=this._mpegAudioL3BitRateTable[u]);break;case 2:33,u<this._mpegAudioL2BitRateTable.length&&(_=this._mpegAudioL2BitRateTable[u]);break;case 3:32,u<this._mpegAudioL1BitRateTable.length&&(_=this._mpegAudioL1BitRateTable[u])}s={bitRate:_,samplingRate:c,channelCount:f,codec:"mp3",originalCodec:"mp3"}}else s=r;return s}},{key:"_parseVideoData",value:function(e,t,n,i,r){if(n<=1)return void l.default.w(this.TAG,"Flv: Invalid video packet, missing VideoData payload!");if(!0!==this._hasVideoFlagOverrided||!1!==this._hasVideo){var s=new Uint8Array(e,t,n)[0],a=(240&s)>>>4,o=15&s;if(7!==o)return void this._onError(m.default.CODEC_UNSUPPORTED,"Flv: Unsupported codec in video frame: "+o);this._parseAVCVideoPacket(e,t+1,n-1,i,r,a)}}},{key:"_parseAVCVideoPacket",value:function(e,t,n,i,r,s){if(n<4)return void l.default.w(this.TAG,"Flv: Invalid AVC packet, missing AVCPacketType or/and CompositionTime");var a=this._littleEndian,o=new DataView(e,t,n),u=o.getUint8(0),d=16777215&o.getUint32(0,!a),h=d<<8>>8;if(0===u)this._parseAVCDecoderConfigurationRecord(e,t+4,n-4);else if(1===u)this._parseAVCVideoData(e,t+4,n-4,i,r,s,h);else if(2!==u)return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid video packet type "+u)}},{key:"_parseAVCDecoderConfigurationRecord",value:function(e,t,n){if(n<7)return void l.default.w(this.TAG,"Flv: Invalid AVCDecoderConfigurationRecord, lack of data!");var i=this._videoMetadata,r=this._videoTrack,s=this._littleEndian,a=new DataView(e,t,n);i?void 0!==i.avcc&&l.default.w(this.TAG,"Found another AVCDecoderConfigurationRecord!"):(!1===this._hasVideo&&!1===this._hasVideoFlagOverrided&&(this._hasVideo=!0,this._mediaInfo.hasVideo=!0),i=this._videoMetadata={},i.type="video",i.id=r.id,i.timescale=this._timescale,i.duration=this._duration);var o=a.getUint8(0),u=a.getUint8(1);a.getUint8(2),a.getUint8(3);if(1!==o||0===u)return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid AVCDecoderConfigurationRecord");if(this._naluLengthSize=1+(3&a.getUint8(4)),3!==this._naluLengthSize&&4!==this._naluLengthSize)return void this._onError(m.default.FORMAT_ERROR,"Flv: Strange NaluLengthSizeMinusOne: "+(this._naluLengthSize-1));var d=31&a.getUint8(5);if(0===d)return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid AVCDecoderConfigurationRecord: No SPS");d>1&&l.default.w(this.TAG,"Flv: Strange AVCDecoderConfigurationRecord: SPS Count = "+d);for(var h=6,f=0;f<d;f++){var _=a.getUint16(h,!s);if(h+=2,0!==_){var p=new Uint8Array(e,t+h,_);h+=_;var v=c.default.parseSPS(p);if(0===f){i.codecWidth=v.codec_size.width,i.codecHeight=v.codec_size.height,i.presentWidth=v.present_size.width,i.presentHeight=v.present_size.height,i.profile=v.profile_string,i.level=v.level_string,i.bitDepth=v.bit_depth,i.chromaFormat=v.chroma_format,i.sarRatio=v.sar_ratio,i.frameRate=v.frame_rate,!1!==v.frame_rate.fixed&&0!==v.frame_rate.fps_num&&0!==v.frame_rate.fps_den||(i.frameRate=this._referenceFrameRate);var g=i.frameRate.fps_den,y=i.frameRate.fps_num;i.refSampleDuration=i.timescale*(g/y);for(var E=p.subarray(1,4),b="avc1.",S=0;S<3;S++){var k=E[S].toString(16);k.length<2&&(k="0"+k),b+=k}i.codec=b;var L=this._mediaInfo;L.width=i.codecWidth,L.height=i.codecHeight,L.fps=i.frameRate.fps,L.profile=i.profile,L.level=i.level,L.refFrames=v.ref_frames,L.chromaFormat=v.chroma_format_string,L.sarNum=i.sarRatio.width,L.sarDen=i.sarRatio.height,L.videoCodec=b,L.hasAudio?null!=L.audioCodec&&(L.mimeType='video/x-flv; codecs="'+L.videoCodec+","+L.audioCodec+'"'):L.mimeType='video/x-flv; codecs="'+L.videoCodec+'"',L.isComplete()&&this._onMediaInfo(L)}}}var R=a.getUint8(h);if(0===R)return void this._onError(m.default.FORMAT_ERROR,"Flv: Invalid AVCDecoderConfigurationRecord: No PPS");R>1&&l.default.w(this.TAG,"Flv: Strange AVCDecoderConfigurationRecord: PPS Count = "+R),h++;for(var A=0;A<R;A++){var w=a.getUint16(h,!s);h+=2,0!==w&&(h+=w)}i.avcc=new Uint8Array(n),i.avcc.set(new Uint8Array(e,t,n),0),l.default.v(this.TAG,"Parsed AVCDecoderConfigurationRecord"),this._isInitialMetadataDispatched()?this._dispatch&&(this._audioTrack.length||this._videoTrack.length)&&this._onDataAvailable(this._audioTrack,this._videoTrack):this._videoInitialMetadataDispatched=!0,this._dispatch=!1,this._onTrackMetadata("video",i)}},{key:"_parseAVCVideoData",value:function(e,t,n,i,r,s,a){for(var o=this._littleEndian,u=new DataView(e,t,n),d=[],h=0,f=0,c=this._naluLengthSize,_=this._timestampBase+i,m=1===s;f<n;){if(f+4>=n){l.default.w(this.TAG,"Malformed Nalu near timestamp "+_+", offset = "+f+", dataSize = "+n);break}var p=u.getUint32(f,!o);if(3===c&&(p>>>=8),p>n-c)return void l.default.w(this.TAG,"Malformed Nalus near timestamp "+_+", NaluSize > DataSize!");var v=31&u.getUint8(f+c);5===v&&(m=!0);var g=new Uint8Array(e,t+f,c+p),y={type:v,data:g};d.push(y),h+=g.byteLength,f+=c+p}if(d.length){var E=this._videoTrack,b={units:d,length:h,isKeyframe:m,dts:_,cts:a,pts:_+a};m&&(b.fileposition=r),E.samples.push(b),E.length+=h}}},{key:"onTrackMetadata",get:function(){return this._onTrackMetadata},set:function(e){this._onTrackMetadata=e}},{key:"onMediaInfo",get:function(){return this._onMediaInfo},set:function(e){this._onMediaInfo=e}},{key:"onMetaDataArrived",get:function(){return this._onMetaDataArrived},set:function(e){this._onMetaDataArrived=e}},{key:"onScriptDataArrived",get:function(){return this._onScriptDataArrived},set:function(e){this._onScriptDataArrived=e}},{key:"onError",get:function(){return this._onError},set:function(e){this._onError=e}},{key:"onDataAvailable",get:function(){return this._onDataAvailable},set:function(e){this._onDataAvailable=e}},{key:"timestampBase",get:function(){return this._timestampBase},set:function(e){this._timestampBase=e}},{key:"overridedDuration",get:function(){return this._duration},set:function(e){this._durationOverrided=!0,this._duration=e,this._mediaInfo.duration=e}},{key:"overridedHasAudio",set:function(e){this._hasAudioFlagOverrided=!0,this._hasAudio=e,this._mediaInfo.hasAudio=e}},{key:"overridedHasVideo",set:function(e){this._hasVideoFlagOverrided=!0,this._hasVideo=e,this._mediaInfo.hasVideo=e}}],[{key:"probe",value:function(e){var t=new Uint8Array(e),n={match:!1};if(70!==t[0]||76!==t[1]||86!==t[2]||1!==t[3])return n;var i=(4&t[4])>>>2!=0,r=0!=(1&t[4]),a=s(t,5);return a<9?n:{match:!0,consumed:a,dataOffset:a,hasAudioTrack:i,hasVideoTrack:r}}}]),e}();n.default=y},{"../core/media-info.js":7,"../utils/exception.js":40,"../utils/logger.js":41,"./amf-parser.js":15,"./demux-errors.js":16,"./sps-parser.js":19}],19:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("./exp-golomb.js"),a=function(e){return e&&e.__esModule?e:{default:e}}(s),o=function(){function e(){i(this,e)}return r(e,null,[{key:"_ebsp2rbsp",value:function(e){for(var t=e,n=t.byteLength,i=new Uint8Array(n),r=0,s=0;s<n;s++)s>=2&&3===t[s]&&0===t[s-1]&&0===t[s-2]||(i[r]=t[s],r++);return new Uint8Array(i.buffer,0,r)}},{key:"parseSPS",value:function(t){var n=e._ebsp2rbsp(t),i=new a.default(n);i.readByte();var r=i.readByte();i.readByte();var s=i.readByte();i.readUEG();var o=e.getProfileString(r),u=e.getLevelString(s),l=1,d=420,h=[0,420,422,444],f=8;if((100===r||110===r||122===r||244===r||44===r||83===r||86===r||118===r||128===r||138===r||144===r)&&(l=i.readUEG(),3===l&&i.readBits(1),l<=3&&(d=h[l]),f=i.readUEG()+8,i.readUEG(),i.readBits(1),i.readBool()))for(var c=3!==l?8:12,_=0;_<c;_++)i.readBool()&&(_<6?e._skipScalingList(i,16):e._skipScalingList(i,64));i.readUEG();var m=i.readUEG();if(0===m)i.readUEG();else if(1===m){i.readBits(1),i.readSEG(),i.readSEG();for(var p=i.readUEG(),v=0;v<p;v++)i.readSEG()}var g=i.readUEG();i.readBits(1);var y=i.readUEG(),E=i.readUEG(),b=i.readBits(1);0===b&&i.readBits(1),i.readBits(1);var S=0,k=0,L=0,R=0;i.readBool()&&(S=i.readUEG(),k=i.readUEG(),L=i.readUEG(),R=i.readUEG());var A=1,w=1,T=0,O=!0,C=0,I=0;if(i.readBool()){if(i.readBool()){var D=i.readByte(),x=[1,12,10,16,40,24,20,32,80,18,15,64,160,4,3,2],M=[1,11,11,11,33,11,11,11,33,11,11,33,99,3,2,1];D>0&&D<16?(A=x[D-1],w=M[D-1]):255===D&&(A=i.readByte()<<8|i.readByte(),w=i.readByte()<<8|i.readByte())}if(i.readBool()&&i.readBool(),i.readBool()&&(i.readBits(4),i.readBool()&&i.readBits(24)),i.readBool()&&(i.readUEG(),i.readUEG()),i.readBool()){var B=i.readBits(32),j=i.readBits(32);O=i.readBool(),C=j,I=2*B,T=C/I}}var P=1;1===A&&1===w||(P=A/w);var U=0,N=0;if(0===l)U=1,N=2-b;else{var F=3===l?1:2,G=1===l?2:1;U=F,N=G*(2-b)}var V=16*(y+1),z=16*(E+1)*(2-b);V-=(S+k)*U,z-=(L+R)*N;var H=Math.ceil(V*P);return i.destroy(),i=null,{profile_string:o,level_string:u,bit_depth:f,ref_frames:g,chroma_format:d,chroma_format_string:e.getChromaFormatString(d),frame_rate:{fixed:O,fps:T,fps_den:I,fps_num:C},sar_ratio:{width:A,height:w},codec_size:{width:V,height:z},present_size:{width:H,height:z}}}},{key:"_skipScalingList",value:function(e,t){for(var n=8,i=8,r=0,s=0;s<t;s++)0!==i&&(r=e.readSEG(),i=(n+r+256)%256),n=0===i?n:i}},{key:"getProfileString",value:function(e){switch(e){case 66:return"Baseline";case 77:return"Main";case 88:return"Extended";case 100:return"High";case 110:return"High10";case 122:return"High422";case 244:return"High444";default:return"Unknown"}}},{key:"getLevelString",value:function(e){return(e/10).toFixed(1)}},{key:"getChromaFormatString",value:function(e){switch(e){case 420:return"4:2:0";case 422:return"4:2:2";case 444:return"4:4:4";default:return"Unknown"}}}]),e}();n.default=o},{"./exp-golomb.js":17}],20:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=e;if(null==n||"object"!==(void 0===n?"undefined":o(n)))throw new S.InvalidArgumentException("MediaDataSource must be an javascript object!");if(!n.hasOwnProperty("type"))throw new S.InvalidArgumentException("MediaDataSource must has type field to indicate video file type!");switch(n.type){case"flv":return new _.default(n,t);default:return new p.default(n,t)}}function s(){return h.default.supportMSEH264Playback()}function a(){return h.default.getFeatureList()}Object.defineProperty(n,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},u=e("./utils/polyfill.js"),l=i(u),d=e("./core/features.js"),h=i(d),f=e("./io/loader.js"),c=e("./player/flv-player.js"),_=i(c),m=e("./player/native-player.js"),p=i(m),v=e("./player/player-events.js"),g=i(v),y=e("./player/player-errors.js"),E=e("./utils/logging-control.js"),b=i(E),S=e("./utils/exception.js");l.default.install();var k={};k.createPlayer=r,k.isSupported=s,k.getFeatureList=a,k.BaseLoader=f.BaseLoader,k.LoaderStatus=f.LoaderStatus,k.LoaderErrors=f.LoaderErrors,k.Events=g.default,k.ErrorTypes=y.ErrorTypes,k.ErrorDetails=y.ErrorDetails,k.FlvPlayer=_.default,k.NativePlayer=p.default,k.LoggingControl=b.default,Object.defineProperty(k,"version",{enumerable:!0,get:function(){return"1.5.0"}}),n.default=k},{"./core/features.js":6,"./io/loader.js":24,"./player/flv-player.js":32,"./player/native-player.js":33,"./player/player-errors.js":34,"./player/player-events.js":35,"./utils/exception.js":40,"./utils/logging-control.js":42,"./utils/polyfill.js":43}],21:[function(e,t,n){"use strict";t.exports=e("./flv.js").default},{"./flv.js":20}],22:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},u=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},l=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),d=e("../utils/logger.js"),h=(i(d),e("../utils/browser.js")),f=i(h),c=e("./loader.js"),_=e("../utils/exception.js"),m=function(e){function t(e,n){r(this,t);var i=s(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"fetch-stream-loader"));return i.TAG="FetchStreamLoader",i._seekHandler=e,i._config=n,i._needStash=!0,i._requestAbort=!1,i._contentLength=null,i._receivedLength=0,i}return a(t,e),l(t,null,[{key:"isSupported",value:function(){try{var e=f.default.msedge&&f.default.version.minor>=15048,t=!f.default.msedge||e;return self.fetch&&self.ReadableStream&&t}catch(e){return!1}}}]),l(t,[{key:"destroy",value:function(){this.isWorking()&&this.abort(),u(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e,t){var n=this;this._dataSource=e,this._range=t;var i=e.url;this._config.reuseRedirectedURL&&void 0!=e.redirectedURL&&(i=e.redirectedURL);var r=this._seekHandler.getConfig(i,t),s=new self.Headers;if("object"===o(r.headers)){var a=r.headers;for(var u in a)a.hasOwnProperty(u)&&s.append(u,a[u])}var l={method:"GET",headers:s,mode:"cors",cache:"default",referrerPolicy:"no-referrer-when-downgrade"};if("object"===o(this._config.headers))for(var d in this._config.headers)s.append(d,this._config.headers[d]);!1===e.cors&&(l.mode="same-origin"),e.withCredentials&&(l.credentials="include"),e.referrerPolicy&&(l.referrerPolicy=e.referrerPolicy),this._status=c.LoaderStatus.kConnecting,self.fetch(r.url,l).then(function(e){if(n._requestAbort)return n._requestAbort=!1,void(n._status=c.LoaderStatus.kIdle);if(e.ok&&e.status>=200&&e.status<=299){if(e.url!==r.url&&n._onURLRedirect){var t=n._seekHandler.removeURLParameters(e.url);n._onURLRedirect(t)}var i=e.headers.get("Content-Length");return null!=i&&(n._contentLength=parseInt(i),0!==n._contentLength&&n._onContentLengthKnown&&n._onContentLengthKnown(n._contentLength)),n._pump.call(n,e.body.getReader())}if(n._status=c.LoaderStatus.kError,!n._onError)throw new _.RuntimeException("FetchStreamLoader: Http code invalid, "+e.status+" "+e.statusText);n._onError(c.LoaderErrors.HTTP_STATUS_CODE_INVALID,{code:e.status,msg:e.statusText})}).catch(function(e){if(n._status=c.LoaderStatus.kError,!n._onError)throw e;n._onError(c.LoaderErrors.EXCEPTION,{code:-1,msg:e.message})})}},{key:"abort",value:function(){this._requestAbort=!0}},{key:"_pump",value:function(e){var t=this;return e.read().then(function(n){if(n.done)if(null!==t._contentLength&&t._receivedLength<t._contentLength){t._status=c.LoaderStatus.kError;var i=c.LoaderErrors.EARLY_EOF,r={code:-1,msg:"Fetch stream meet Early-EOF"};if(!t._onError)throw new _.RuntimeException(r.msg);t._onError(i,r)}else t._status=c.LoaderStatus.kComplete,t._onComplete&&t._onComplete(t._range.from,t._range.from+t._receivedLength-1);else{if(!0===t._requestAbort)return t._requestAbort=!1,t._status=c.LoaderStatus.kComplete,e.cancel();t._status=c.LoaderStatus.kBuffering;var s=n.value.buffer,a=t._range.from+t._receivedLength;t._receivedLength+=s.byteLength,t._onDataArrival&&t._onDataArrival(s,a,t._receivedLength),t._pump(e)}}).catch(function(e){if(11!==e.code||!f.default.msedge){t._status=c.LoaderStatus.kError;var n=0,i=null;if(19!==e.code&&"network error"!==e.message||!(null===t._contentLength||null!==t._contentLength&&t._receivedLength<t._contentLength)?(n=c.LoaderErrors.EXCEPTION,i={code:e.code,msg:e.message}):(n=c.LoaderErrors.EARLY_EOF,i={code:e.code,msg:"Fetch stream meet Early-EOF"}),!t._onError)throw new _.RuntimeException(i.msg);t._onError(n,i)}})}}]),t}(c.BaseLoader);n.default=m},{"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],23:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("../utils/logger.js"),o=i(a),u=e("./speed-sampler.js"),l=i(u),d=e("./loader.js"),h=e("./fetch-stream-loader.js"),f=i(h),c=e("./xhr-moz-chunked-loader.js"),_=i(c),m=e("./xhr-msstream-loader.js"),p=(i(m),e("./xhr-range-loader.js")),v=i(p),g=e("./websocket-loader.js"),y=i(g),E=e("./range-seek-handler.js"),b=i(E),S=e("./param-seek-handler.js"),k=i(S),L=e("../utils/exception.js"),R=function(){function e(t,n,i){r(this,e),this.TAG="IOController",this._config=n,this._extraData=i,this._stashInitialSize=393216,void 0!=n.stashInitialSize&&n.stashInitialSize>0&&(this._stashInitialSize=n.stashInitialSize),this._stashUsed=0,this._stashSize=this._stashInitialSize,this._bufferSize=3145728,this._stashBuffer=new ArrayBuffer(this._bufferSize),this._stashByteStart=0,this._enableStash=!0,!1===n.enableStashBuffer&&(this._enableStash=!1),this._loader=null,this._loaderClass=null,this._seekHandler=null,this._dataSource=t,this._isWebSocketURL=/wss?:\/\/(.+?)/.test(t.url),this._refTotalLength=t.filesize?t.filesize:null,this._totalLength=this._refTotalLength,this._fullRequestFlag=!1,this._currentRange=null,this._redirectedURL=null,this._speedNormalized=0,this._speedSampler=new l.default,this._speedNormalizeList=[64,128,256,384,512,768,1024,1536,2048,3072,4096],this._isEarlyEofReconnecting=!1,this._paused=!1,this._resumeFrom=0,this._onDataArrival=null,this._onSeeked=null,this._onError=null,this._onComplete=null,this._onRedirect=null,this._onRecoveredEarlyEof=null,this._selectSeekHandler(),this._selectLoader(),this._createLoader()}return s(e,[{key:"destroy",value:function(){this._loader.isWorking()&&this._loader.abort(),this._loader.destroy(),this._loader=null,this._loaderClass=null,this._dataSource=null,this._stashBuffer=null,this._stashUsed=this._stashSize=this._bufferSize=this._stashByteStart=0,this._currentRange=null,this._speedSampler=null,this._isEarlyEofReconnecting=!1,this._onDataArrival=null,this._onSeeked=null,this._onError=null,this._onComplete=null,this._onRedirect=null,this._onRecoveredEarlyEof=null,this._extraData=null}},{key:"isWorking",value:function(){return this._loader&&this._loader.isWorking()&&!this._paused}},{key:"isPaused",value:function(){return this._paused}},{key:"_selectSeekHandler",value:function(){var e=this._config;if("range"===e.seekType)this._seekHandler=new b.default(this._config.rangeLoadZeroStart);else if("param"===e.seekType){var t=e.seekParamStart||"bstart",n=e.seekParamEnd||"bend";this._seekHandler=new k.default(t,n)}else{if("custom"!==e.seekType)throw new L.InvalidArgumentException("Invalid seekType in config: "+e.seekType);if("function"!=typeof e.customSeekHandler)throw new L.InvalidArgumentException("Custom seekType specified in config but invalid customSeekHandler!");this._seekHandler=new e.customSeekHandler}}},{key:"_selectLoader",value:function(){if(null!=this._config.customLoader)this._loaderClass=this._config.customLoader;else if(this._isWebSocketURL)this._loaderClass=y.default;else if(f.default.isSupported())this._loaderClass=f.default;else if(_.default.isSupported())this._loaderClass=_.default;else{if(!v.default.isSupported())throw new L.RuntimeException("Your browser doesn't support xhr with arraybuffer responseType!");this._loaderClass=v.default}}},{key:"_createLoader",value:function(){this._loader=new this._loaderClass(this._seekHandler,this._config),!1===this._loader.needStashBuffer&&(this._enableStash=!1),this._loader.onContentLengthKnown=this._onContentLengthKnown.bind(this),this._loader.onURLRedirect=this._onURLRedirect.bind(this),this._loader.onDataArrival=this._onLoaderChunkArrival.bind(this),this._loader.onComplete=this._onLoaderComplete.bind(this),this._loader.onError=this._onLoaderError.bind(this)}},{key:"open",value:function(e){this._currentRange={from:0,to:-1},e&&(this._currentRange.from=e),this._speedSampler.reset(),e||(this._fullRequestFlag=!0),this._loader.open(this._dataSource,Object.assign({},this._currentRange))}},{key:"abort",value:function(){this._loader.abort(),this._paused&&(this._paused=!1,this._resumeFrom=0)}},{key:"pause",value:function(){this.isWorking()&&(this._loader.abort(),0!==this._stashUsed?(this._resumeFrom=this._stashByteStart,this._currentRange.to=this._stashByteStart-1):this._resumeFrom=this._currentRange.to+1,this._stashUsed=0,this._stashByteStart=0,this._paused=!0)}},{key:"resume",value:function(){if(this._paused){this._paused=!1;var e=this._resumeFrom;this._resumeFrom=0,this._internalSeek(e,!0)}}},{key:"seek",value:function(e){this._paused=!1,this._stashUsed=0,this._stashByteStart=0,this._internalSeek(e,!0)}},{key:"_internalSeek",value:function(e,t){this._loader.isWorking()&&this._loader.abort(),this._flushStashBuffer(t),this._loader.destroy(),this._loader=null;var n={from:e,to:-1};this._currentRange={from:n.from,to:-1},this._speedSampler.reset(),this._stashSize=this._stashInitialSize,this._createLoader(),this._loader.open(this._dataSource,n),this._onSeeked&&this._onSeeked()}},{key:"updateUrl",value:function(e){if(!e||"string"!=typeof e||0===e.length)throw new L.InvalidArgumentException("Url must be a non-empty string!");this._dataSource.url=e}},{key:"_expandBuffer",value:function(e){for(var t=this._stashSize;t+1048576<e;)t*=2;if((t+=1048576)!==this._bufferSize){var n=new ArrayBuffer(t);if(this._stashUsed>0){var i=new Uint8Array(this._stashBuffer,0,this._stashUsed);new Uint8Array(n,0,t).set(i,0)}this._stashBuffer=n,this._bufferSize=t}}},{key:"_normalizeSpeed",value:function(e){var t=this._speedNormalizeList,n=t.length-1,i=0,r=0,s=n;if(e<t[0])return t[0];for(;r<=s;){if((i=r+Math.floor((s-r)/2))===n||e>=t[i]&&e<t[i+1])return t[i];t[i]<e?r=i+1:s=i-1}}},{key:"_adjustStashSize",value:function(e){var t=0;(t=this._config.isLive?e:e<512?e:e>=512&&e<=1024?Math.floor(1.5*e):2*e)>8192&&(t=8192);var n=1024*t+1048576;this._bufferSize<n&&this._expandBuffer(n),this._stashSize=1024*t}},{key:"_dispatchChunks",value:function(e,t){return this._currentRange.to=t+e.byteLength-1,this._onDataArrival(e,t)}},{key:"_onURLRedirect",value:function(e){this._redirectedURL=e,this._onRedirect&&this._onRedirect(e)}},{key:"_onContentLengthKnown",value:function(e){e&&this._fullRequestFlag&&(this._totalLength=e,this._fullRequestFlag=!1)}},{key:"_onLoaderChunkArrival",value:function(e,t,n){if(!this._onDataArrival)throw new L.IllegalStateException("IOController: No existing consumer (onDataArrival) callback!");if(!this._paused){this._isEarlyEofReconnecting&&(this._isEarlyEofReconnecting=!1,this._onRecoveredEarlyEof&&this._onRecoveredEarlyEof()),this._speedSampler.addBytes(e.byteLength);var i=this._speedSampler.lastSecondKBps;if(0!==i){var r=this._normalizeSpeed(i);this._speedNormalized!==r&&(this._speedNormalized=r,this._adjustStashSize(r))}if(this._enableStash)if(0===this._stashUsed&&0===this._stashByteStart&&(this._stashByteStart=t),this._stashUsed+e.byteLength<=this._stashSize){var s=new Uint8Array(this._stashBuffer,0,this._stashSize);s.set(new Uint8Array(e),this._stashUsed),this._stashUsed+=e.byteLength}else{var a=new Uint8Array(this._stashBuffer,0,this._bufferSize);if(this._stashUsed>0){var o=this._stashBuffer.slice(0,this._stashUsed),u=this._dispatchChunks(o,this._stashByteStart);if(u<o.byteLength){if(u>0){var l=new Uint8Array(o,u);a.set(l,0),this._stashUsed=l.byteLength,this._stashByteStart+=u}}else this._stashUsed=0,this._stashByteStart+=u;this._stashUsed+e.byteLength>this._bufferSize&&(this._expandBuffer(this._stashUsed+e.byteLength),a=new Uint8Array(this._stashBuffer,0,this._bufferSize)),a.set(new Uint8Array(e),this._stashUsed),this._stashUsed+=e.byteLength}else{var d=this._dispatchChunks(e,t);if(d<e.byteLength){var h=e.byteLength-d;h>this._bufferSize&&(this._expandBuffer(h),a=new Uint8Array(this._stashBuffer,0,this._bufferSize)),a.set(new Uint8Array(e,d),0),this._stashUsed+=h,this._stashByteStart=t+d}}}else if(0===this._stashUsed){var f=this._dispatchChunks(e,t);if(f<e.byteLength){var c=e.byteLength-f;c>this._bufferSize&&this._expandBuffer(c);var _=new Uint8Array(this._stashBuffer,0,this._bufferSize);_.set(new Uint8Array(e,f),0),this._stashUsed+=c,this._stashByteStart=t+f}}else{this._stashUsed+e.byteLength>this._bufferSize&&this._expandBuffer(this._stashUsed+e.byteLength);var m=new Uint8Array(this._stashBuffer,0,this._bufferSize);m.set(new Uint8Array(e),this._stashUsed),this._stashUsed+=e.byteLength;var p=this._dispatchChunks(this._stashBuffer.slice(0,this._stashUsed),this._stashByteStart);if(p<this._stashUsed&&p>0){var v=new Uint8Array(this._stashBuffer,p);m.set(v,0)}this._stashUsed-=p,this._stashByteStart+=p}}}},{key:"_flushStashBuffer",value:function(e){if(this._stashUsed>0){var t=this._stashBuffer.slice(0,this._stashUsed),n=this._dispatchChunks(t,this._stashByteStart),i=t.byteLength-n;if(n<t.byteLength){if(!e){if(n>0){var r=new Uint8Array(this._stashBuffer,0,this._bufferSize),s=new Uint8Array(t,n);r.set(s,0),this._stashUsed=s.byteLength,this._stashByteStart+=n}return 0}o.default.w(this.TAG,i+" bytes unconsumed data remain when flush buffer, dropped")}return this._stashUsed=0,this._stashByteStart=0,i}return 0}},{key:"_onLoaderComplete",value:function(e,t){this._flushStashBuffer(!0),this._onComplete&&this._onComplete(this._extraData)}},{key:"_onLoaderError",value:function(e,t){switch(o.default.e(this.TAG,"Loader error, code = "+t.code+", msg = "+t.msg),this._flushStashBuffer(!1),this._isEarlyEofReconnecting&&(this._isEarlyEofReconnecting=!1,e=d.LoaderErrors.UNRECOVERABLE_EARLY_EOF),e){case d.LoaderErrors.EARLY_EOF:if(!this._config.isLive&&this._totalLength){var n=this._currentRange.to+1;return void(n<this._totalLength&&(o.default.w(this.TAG,"Connection lost, trying reconnect..."),this._isEarlyEofReconnecting=!0,this._internalSeek(n,!1)))}e=d.LoaderErrors.UNRECOVERABLE_EARLY_EOF;break;case d.LoaderErrors.UNRECOVERABLE_EARLY_EOF:case d.LoaderErrors.CONNECTING_TIMEOUT:case d.LoaderErrors.HTTP_STATUS_CODE_INVALID:case d.LoaderErrors.EXCEPTION:}if(!this._onError)throw new L.RuntimeException("IOException: "+t.msg);this._onError(e,t)}},{key:"status",get:function(){return this._loader.status}},{key:"extraData",get:function(){return this._extraData},set:function(e){this._extraData=e}},{key:"onDataArrival",get:function(){return this._onDataArrival},set:function(e){this._onDataArrival=e}},{key:"onSeeked",get:function(){return this._onSeeked},set:function(e){this._onSeeked=e}},{key:"onError",get:function(){return this._onError},set:function(e){this._onError=e}},{key:"onComplete",get:function(){return this._onComplete},set:function(e){this._onComplete=e}},{key:"onRedirect",get:function(){return this._onRedirect},set:function(e){this._onRedirect=e}},{key:"onRecoveredEarlyEof",get:function(){return this._onRecoveredEarlyEof},set:function(e){this._onRecoveredEarlyEof=e}},{key:"currentURL",get:function(){return this._dataSource.url}},{key:"hasRedirect",get:function(){return null!=this._redirectedURL||void 0!=this._dataSource.redirectedURL}},{key:"currentRedirectedURL",get:function(){return this._redirectedURL||this._dataSource.redirectedURL}},{key:"currentSpeed",get:function(){return this._loaderClass===v.default?this._loader.currentSpeed:this._speedSampler.lastSecondKBps}},{key:"loaderType",get:function(){return this._loader.type}}]),e}();n.default=R},{"../utils/exception.js":40,"../utils/logger.js":41,"./fetch-stream-loader.js":22,"./loader.js":24, | |
| 16 | + "./param-seek-handler.js":25,"./range-seek-handler.js":26,"./speed-sampler.js":27,"./websocket-loader.js":28,"./xhr-moz-chunked-loader.js":29,"./xhr-msstream-loader.js":30,"./xhr-range-loader.js":31}],24:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.BaseLoader=n.LoaderErrors=n.LoaderStatus=void 0;var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("../utils/exception.js"),a=n.LoaderStatus={kIdle:0,kConnecting:1,kBuffering:2,kError:3,kComplete:4};n.LoaderErrors={OK:"OK",EXCEPTION:"Exception",HTTP_STATUS_CODE_INVALID:"HttpStatusCodeInvalid",CONNECTING_TIMEOUT:"ConnectingTimeout",EARLY_EOF:"EarlyEof",UNRECOVERABLE_EARLY_EOF:"UnrecoverableEarlyEof"},n.BaseLoader=function(){function e(t){i(this,e),this._type=t||"undefined",this._status=a.kIdle,this._needStash=!1,this._onContentLengthKnown=null,this._onURLRedirect=null,this._onDataArrival=null,this._onError=null,this._onComplete=null}return r(e,[{key:"destroy",value:function(){this._status=a.kIdle,this._onContentLengthKnown=null,this._onURLRedirect=null,this._onDataArrival=null,this._onError=null,this._onComplete=null}},{key:"isWorking",value:function(){return this._status===a.kConnecting||this._status===a.kBuffering}},{key:"open",value:function(e,t){throw new s.NotImplementedException("Unimplemented abstract function!")}},{key:"abort",value:function(){throw new s.NotImplementedException("Unimplemented abstract function!")}},{key:"type",get:function(){return this._type}},{key:"status",get:function(){return this._status}},{key:"needStashBuffer",get:function(){return this._needStash}},{key:"onContentLengthKnown",get:function(){return this._onContentLengthKnown},set:function(e){this._onContentLengthKnown=e}},{key:"onURLRedirect",get:function(){return this._onURLRedirect},set:function(e){this._onURLRedirect=e}},{key:"onDataArrival",get:function(){return this._onDataArrival},set:function(e){this._onDataArrival=e}},{key:"onError",get:function(){return this._onError},set:function(e){this._onError=e}},{key:"onComplete",get:function(){return this._onComplete},set:function(e){this._onComplete=e}}]),e}()},{"../utils/exception.js":40}],25:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(t,n){i(this,e),this._startName=t,this._endName=n}return r(e,[{key:"getConfig",value:function(e,t){var n=e;if(0!==t.from||-1!==t.to){var i=!0;-1===n.indexOf("?")&&(n+="?",i=!1),i&&(n+="&"),n+=this._startName+"="+t.from.toString(),-1!==t.to&&(n+="&"+this._endName+"="+t.to.toString())}return{url:n,headers:{}}}},{key:"removeURLParameters",value:function(e){var t=e.split("?")[0],n=void 0,i=e.indexOf("?");-1!==i&&(n=e.substring(i+1));var r="";if(void 0!=n&&n.length>0)for(var s=n.split("&"),a=0;a<s.length;a++){var o=s[a].split("="),u=a>0;o[0]!==this._startName&&o[0]!==this._endName&&(u&&(r+="&"),r+=s[a])}return 0===r.length?t:t+"?"+r}}]),e}();n.default=s},{}],26:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(t){i(this,e),this._zeroStart=t||!1}return r(e,[{key:"getConfig",value:function(e,t){var n={};if(0!==t.from||-1!==t.to){var i=void 0;i=-1!==t.to?"bytes="+t.from.toString()+"-"+t.to.toString():"bytes="+t.from.toString()+"-",n.Range=i}else this._zeroStart&&(n.Range="bytes=0-");return{url:e,headers:n}}},{key:"removeURLParameters",value:function(e){return e}}]),e}();n.default=s},{}],27:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(){i(this,e),this._firstCheckpoint=0,this._lastCheckpoint=0,this._intervalBytes=0,this._totalBytes=0,this._lastSecondBytes=0,self.performance&&self.performance.now?this._now=self.performance.now.bind(self.performance):this._now=Date.now}return r(e,[{key:"reset",value:function(){this._firstCheckpoint=this._lastCheckpoint=0,this._totalBytes=this._intervalBytes=0,this._lastSecondBytes=0}},{key:"addBytes",value:function(e){0===this._firstCheckpoint?(this._firstCheckpoint=this._now(),this._lastCheckpoint=this._firstCheckpoint,this._intervalBytes+=e,this._totalBytes+=e):this._now()-this._lastCheckpoint<1e3?(this._intervalBytes+=e,this._totalBytes+=e):(this._lastSecondBytes=this._intervalBytes,this._intervalBytes=e,this._totalBytes+=e,this._lastCheckpoint=this._now())}},{key:"currentKBps",get:function(){this.addBytes(0);var e=(this._now()-this._lastCheckpoint)/1e3;return 0==e&&(e=1),this._intervalBytes/e/1024}},{key:"lastSecondKBps",get:function(){return this.addBytes(0),0!==this._lastSecondBytes?this._lastSecondBytes/1024:this._now()-this._lastCheckpoint>=500?this.currentKBps:0}},{key:"averageKBps",get:function(){var e=(this._now()-this._firstCheckpoint)/1e3;return this._totalBytes/e/1024}}]),e}();n.default=s},{}],28:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var a=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},o=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),u=e("../utils/logger.js"),l=(function(e){e&&e.__esModule}(u),e("./loader.js")),d=e("../utils/exception.js"),h=function(e){function t(){i(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"websocket-loader"));return e.TAG="WebSocketLoader",e._needStash=!0,e._ws=null,e._requestAbort=!1,e._receivedLength=0,e}return s(t,e),o(t,null,[{key:"isSupported",value:function(){try{return void 0!==self.WebSocket}catch(e){return!1}}}]),o(t,[{key:"destroy",value:function(){this._ws&&this.abort(),a(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e){try{var t=this._ws=new self.WebSocket(e.url);t.binaryType="arraybuffer",t.onopen=this._onWebSocketOpen.bind(this),t.onclose=this._onWebSocketClose.bind(this),t.onmessage=this._onWebSocketMessage.bind(this),t.onerror=this._onWebSocketError.bind(this),this._status=l.LoaderStatus.kConnecting}catch(e){this._status=l.LoaderStatus.kError;var n={code:e.code,msg:e.message};if(!this._onError)throw new d.RuntimeException(n.msg);this._onError(l.LoaderErrors.EXCEPTION,n)}}},{key:"abort",value:function(){var e=this._ws;!e||0!==e.readyState&&1!==e.readyState||(this._requestAbort=!0,e.close()),this._ws=null,this._status=l.LoaderStatus.kComplete}},{key:"_onWebSocketOpen",value:function(e){this._status=l.LoaderStatus.kBuffering}},{key:"_onWebSocketClose",value:function(e){if(!0===this._requestAbort)return void(this._requestAbort=!1);this._status=l.LoaderStatus.kComplete,this._onComplete&&this._onComplete(0,this._receivedLength-1)}},{key:"_onWebSocketMessage",value:function(e){var t=this;if(e.data instanceof ArrayBuffer)this._dispatchArrayBuffer(e.data);else if(e.data instanceof Blob){var n=new FileReader;n.onload=function(){t._dispatchArrayBuffer(n.result)},n.readAsArrayBuffer(e.data)}else{this._status=l.LoaderStatus.kError;var i={code:-1,msg:"Unsupported WebSocket message type: "+e.data.constructor.name};if(!this._onError)throw new d.RuntimeException(i.msg);this._onError(l.LoaderErrors.EXCEPTION,i)}}},{key:"_dispatchArrayBuffer",value:function(e){var t=e,n=this._receivedLength;this._receivedLength+=t.byteLength,this._onDataArrival&&this._onDataArrival(t,n,this._receivedLength)}},{key:"_onWebSocketError",value:function(e){this._status=l.LoaderStatus.kError;var t={code:e.code,msg:e.message};if(!this._onError)throw new d.RuntimeException(t.msg);this._onError(l.LoaderErrors.EXCEPTION,t)}}]),t}(l.BaseLoader);n.default=h},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],29:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},u=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),l=e("../utils/logger.js"),d=function(e){return e&&e.__esModule?e:{default:e}}(l),h=e("./loader.js"),f=e("../utils/exception.js"),c=function(e){function t(e,n){i(this,t);var s=r(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"xhr-moz-chunked-loader"));return s.TAG="MozChunkedLoader",s._seekHandler=e,s._config=n,s._needStash=!0,s._xhr=null,s._requestAbort=!1,s._contentLength=null,s._receivedLength=0,s}return s(t,e),u(t,null,[{key:"isSupported",value:function(){try{var e=new XMLHttpRequest;return e.open("GET","https://example.com",!0),e.responseType="moz-chunked-arraybuffer","moz-chunked-arraybuffer"===e.responseType}catch(e){return d.default.w("MozChunkedLoader",e.message),!1}}}]),u(t,[{key:"destroy",value:function(){this.isWorking()&&this.abort(),this._xhr&&(this._xhr.onreadystatechange=null,this._xhr.onprogress=null,this._xhr.onloadend=null,this._xhr.onerror=null,this._xhr=null),o(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e,t){this._dataSource=e,this._range=t;var n=e.url;this._config.reuseRedirectedURL&&void 0!=e.redirectedURL&&(n=e.redirectedURL);var i=this._seekHandler.getConfig(n,t);this._requestURL=i.url;var r=this._xhr=new XMLHttpRequest;if(r.open("GET",i.url,!0),r.responseType="moz-chunked-arraybuffer",r.onreadystatechange=this._onReadyStateChange.bind(this),r.onprogress=this._onProgress.bind(this),r.onloadend=this._onLoadEnd.bind(this),r.onerror=this._onXhrError.bind(this),e.withCredentials&&(r.withCredentials=!0),"object"===a(i.headers)){var s=i.headers;for(var o in s)s.hasOwnProperty(o)&&r.setRequestHeader(o,s[o])}if("object"===a(this._config.headers)){var u=this._config.headers;for(var l in u)u.hasOwnProperty(l)&&r.setRequestHeader(l,u[l])}this._status=h.LoaderStatus.kConnecting,r.send()}},{key:"abort",value:function(){this._requestAbort=!0,this._xhr&&this._xhr.abort(),this._status=h.LoaderStatus.kComplete}},{key:"_onReadyStateChange",value:function(e){var t=e.target;if(2===t.readyState){if(void 0!=t.responseURL&&t.responseURL!==this._requestURL&&this._onURLRedirect){var n=this._seekHandler.removeURLParameters(t.responseURL);this._onURLRedirect(n)}if(0!==t.status&&(t.status<200||t.status>299)){if(this._status=h.LoaderStatus.kError,!this._onError)throw new f.RuntimeException("MozChunkedLoader: Http code invalid, "+t.status+" "+t.statusText);this._onError(h.LoaderErrors.HTTP_STATUS_CODE_INVALID,{code:t.status,msg:t.statusText})}else this._status=h.LoaderStatus.kBuffering}}},{key:"_onProgress",value:function(e){if(this._status!==h.LoaderStatus.kError){null===this._contentLength&&null!==e.total&&0!==e.total&&(this._contentLength=e.total,this._onContentLengthKnown&&this._onContentLengthKnown(this._contentLength));var t=e.target.response,n=this._range.from+this._receivedLength;this._receivedLength+=t.byteLength,this._onDataArrival&&this._onDataArrival(t,n,this._receivedLength)}}},{key:"_onLoadEnd",value:function(e){if(!0===this._requestAbort)return void(this._requestAbort=!1);this._status!==h.LoaderStatus.kError&&(this._status=h.LoaderStatus.kComplete,this._onComplete&&this._onComplete(this._range.from,this._range.from+this._receivedLength-1))}},{key:"_onXhrError",value:function(e){this._status=h.LoaderStatus.kError;var t=0,n=null;if(this._contentLength&&e.loaded<this._contentLength?(t=h.LoaderErrors.EARLY_EOF,n={code:-1,msg:"Moz-Chunked stream meet Early-Eof"}):(t=h.LoaderErrors.EXCEPTION,n={code:-1,msg:e.constructor.name+" "+e.type}),!this._onError)throw new f.RuntimeException(n.msg);this._onError(t,n)}}]),t}(h.BaseLoader);n.default=c},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],30:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},u=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),l=e("../utils/logger.js"),d=function(e){return e&&e.__esModule?e:{default:e}}(l),h=e("./loader.js"),f=e("../utils/exception.js"),c=function(e){function t(e,n){i(this,t);var s=r(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"xhr-msstream-loader"));return s.TAG="MSStreamLoader",s._seekHandler=e,s._config=n,s._needStash=!0,s._xhr=null,s._reader=null,s._totalRange=null,s._currentRange=null,s._currentRequestURL=null,s._currentRedirectedURL=null,s._contentLength=null,s._receivedLength=0,s._bufferLimit=16777216,s._lastTimeBufferSize=0,s._isReconnecting=!1,s}return s(t,e),u(t,null,[{key:"isSupported",value:function(){try{if(void 0===self.MSStream||void 0===self.MSStreamReader)return!1;var e=new XMLHttpRequest;return e.open("GET","https://example.com",!0),e.responseType="ms-stream","ms-stream"===e.responseType}catch(e){return d.default.w("MSStreamLoader",e.message),!1}}}]),u(t,[{key:"destroy",value:function(){this.isWorking()&&this.abort(),this._reader&&(this._reader.onprogress=null,this._reader.onload=null,this._reader.onerror=null,this._reader=null),this._xhr&&(this._xhr.onreadystatechange=null,this._xhr=null),o(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e,t){this._internalOpen(e,t,!1)}},{key:"_internalOpen",value:function(e,t,n){this._dataSource=e,n?this._currentRange=t:this._totalRange=t;var i=e.url;this._config.reuseRedirectedURL&&(void 0!=this._currentRedirectedURL?i=this._currentRedirectedURL:void 0!=e.redirectedURL&&(i=e.redirectedURL));var r=this._seekHandler.getConfig(i,t);this._currentRequestURL=r.url;var s=this._reader=new self.MSStreamReader;s.onprogress=this._msrOnProgress.bind(this),s.onload=this._msrOnLoad.bind(this),s.onerror=this._msrOnError.bind(this);var o=this._xhr=new XMLHttpRequest;if(o.open("GET",r.url,!0),o.responseType="ms-stream",o.onreadystatechange=this._xhrOnReadyStateChange.bind(this),o.onerror=this._xhrOnError.bind(this),e.withCredentials&&(o.withCredentials=!0),"object"===a(r.headers)){var u=r.headers;for(var l in u)u.hasOwnProperty(l)&&o.setRequestHeader(l,u[l])}if("object"===a(this._config.headers)){var d=this._config.headers;for(var f in d)d.hasOwnProperty(f)&&o.setRequestHeader(f,d[f])}this._isReconnecting?this._isReconnecting=!1:this._status=h.LoaderStatus.kConnecting,o.send()}},{key:"abort",value:function(){this._internalAbort(),this._status=h.LoaderStatus.kComplete}},{key:"_internalAbort",value:function(){this._reader&&(1===this._reader.readyState&&this._reader.abort(),this._reader.onprogress=null,this._reader.onload=null,this._reader.onerror=null,this._reader=null),this._xhr&&(this._xhr.abort(),this._xhr.onreadystatechange=null,this._xhr=null)}},{key:"_xhrOnReadyStateChange",value:function(e){var t=e.target;if(2===t.readyState)if(t.status>=200&&t.status<=299){if(this._status=h.LoaderStatus.kBuffering,void 0!=t.responseURL){var n=this._seekHandler.removeURLParameters(t.responseURL);t.responseURL!==this._currentRequestURL&&n!==this._currentRedirectedURL&&(this._currentRedirectedURL=n,this._onURLRedirect&&this._onURLRedirect(n))}var i=t.getResponseHeader("Content-Length");if(null!=i&&null==this._contentLength){var r=parseInt(i);r>0&&(this._contentLength=r,this._onContentLengthKnown&&this._onContentLengthKnown(this._contentLength))}}else{if(this._status=h.LoaderStatus.kError,!this._onError)throw new f.RuntimeException("MSStreamLoader: Http code invalid, "+t.status+" "+t.statusText);this._onError(h.LoaderErrors.HTTP_STATUS_CODE_INVALID,{code:t.status,msg:t.statusText})}else if(3===t.readyState&&t.status>=200&&t.status<=299){this._status=h.LoaderStatus.kBuffering;var s=t.response;this._reader.readAsArrayBuffer(s)}}},{key:"_xhrOnError",value:function(e){this._status=h.LoaderStatus.kError;var t=h.LoaderErrors.EXCEPTION,n={code:-1,msg:e.constructor.name+" "+e.type};if(!this._onError)throw new f.RuntimeException(n.msg);this._onError(t,n)}},{key:"_msrOnProgress",value:function(e){var t=e.target,n=t.result;if(null==n)return void this._doReconnectIfNeeded();var i=n.slice(this._lastTimeBufferSize);this._lastTimeBufferSize=n.byteLength;var r=this._totalRange.from+this._receivedLength;this._receivedLength+=i.byteLength,this._onDataArrival&&this._onDataArrival(i,r,this._receivedLength),n.byteLength>=this._bufferLimit&&(d.default.v(this.TAG,"MSStream buffer exceeded max size near "+(r+i.byteLength)+", reconnecting..."),this._doReconnectIfNeeded())}},{key:"_doReconnectIfNeeded",value:function(){if(null==this._contentLength||this._receivedLength<this._contentLength){this._isReconnecting=!0,this._lastTimeBufferSize=0,this._internalAbort();var e={from:this._totalRange.from+this._receivedLength,to:-1};this._internalOpen(this._dataSource,e,!0)}}},{key:"_msrOnLoad",value:function(e){this._status=h.LoaderStatus.kComplete,this._onComplete&&this._onComplete(this._totalRange.from,this._totalRange.from+this._receivedLength-1)}},{key:"_msrOnError",value:function(e){this._status=h.LoaderStatus.kError;var t=0,n=null;if(this._contentLength&&this._receivedLength<this._contentLength?(t=h.LoaderErrors.EARLY_EOF,n={code:-1,msg:"MSStream meet Early-Eof"}):(t=h.LoaderErrors.EARLY_EOF,n={code:-1,msg:e.constructor.name+" "+e.type}),!this._onError)throw new f.RuntimeException(n.msg);this._onError(t,n)}}]),t}(h.BaseLoader);n.default=c},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],31:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(n,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},u=function e(t,n,i){null===t&&(t=Function.prototype);var r=Object.getOwnPropertyDescriptor(t,n);if(void 0===r){var s=Object.getPrototypeOf(t);return null===s?void 0:e(s,n,i)}if("value"in r)return r.value;var a=r.get;if(void 0!==a)return a.call(i)},l=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),d=e("../utils/logger.js"),h=i(d),f=e("./speed-sampler.js"),c=i(f),_=e("./loader.js"),m=e("../utils/exception.js"),p=function(e){function t(e,n){r(this,t);var i=s(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,"xhr-range-loader"));return i.TAG="RangeLoader",i._seekHandler=e,i._config=n,i._needStash=!1,i._chunkSizeKBList=[128,256,384,512,768,1024,1536,2048,3072,4096,5120,6144,7168,8192],i._currentChunkSizeKB=384,i._currentSpeedNormalized=0,i._zeroSpeedChunkCount=0,i._xhr=null,i._speedSampler=new c.default,i._requestAbort=!1,i._waitForTotalLength=!1,i._totalLengthReceived=!1,i._currentRequestURL=null,i._currentRedirectedURL=null,i._currentRequestRange=null,i._totalLength=null,i._contentLength=null,i._receivedLength=0,i._lastTimeLoaded=0,i}return a(t,e),l(t,null,[{key:"isSupported",value:function(){try{var e=new XMLHttpRequest;return e.open("GET","https://example.com",!0),e.responseType="arraybuffer","arraybuffer"===e.responseType}catch(e){return h.default.w("RangeLoader",e.message),!1}}}]),l(t,[{key:"destroy",value:function(){this.isWorking()&&this.abort(),this._xhr&&(this._xhr.onreadystatechange=null,this._xhr.onprogress=null,this._xhr.onload=null,this._xhr.onerror=null,this._xhr=null),u(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"destroy",this).call(this)}},{key:"open",value:function(e,t){this._dataSource=e,this._range=t,this._status=_.LoaderStatus.kConnecting;var n=!1;void 0!=this._dataSource.filesize&&0!==this._dataSource.filesize&&(n=!0,this._totalLength=this._dataSource.filesize),this._totalLengthReceived||n?this._openSubRange():(this._waitForTotalLength=!0,this._internalOpen(this._dataSource,{from:0,to:-1}))}},{key:"_openSubRange",value:function(){var e=1024*this._currentChunkSizeKB,t=this._range.from+this._receivedLength,n=t+e;null!=this._contentLength&&n-this._range.from>=this._contentLength&&(n=this._range.from+this._contentLength-1),this._currentRequestRange={from:t,to:n},this._internalOpen(this._dataSource,this._currentRequestRange)}},{key:"_internalOpen",value:function(e,t){this._lastTimeLoaded=0;var n=e.url;this._config.reuseRedirectedURL&&(void 0!=this._currentRedirectedURL?n=this._currentRedirectedURL:void 0!=e.redirectedURL&&(n=e.redirectedURL));var i=this._seekHandler.getConfig(n,t);this._currentRequestURL=i.url;var r=this._xhr=new XMLHttpRequest;if(r.open("GET",i.url,!0),r.responseType="arraybuffer",r.onreadystatechange=this._onReadyStateChange.bind(this),r.onprogress=this._onProgress.bind(this),r.onload=this._onLoad.bind(this),r.onerror=this._onXhrError.bind(this),e.withCredentials&&(r.withCredentials=!0),"object"===o(i.headers)){var s=i.headers;for(var a in s)s.hasOwnProperty(a)&&r.setRequestHeader(a,s[a])}if("object"===o(this._config.headers)){var u=this._config.headers;for(var l in u)u.hasOwnProperty(l)&&r.setRequestHeader(l,u[l])}r.send()}},{key:"abort",value:function(){this._requestAbort=!0,this._internalAbort(),this._status=_.LoaderStatus.kComplete}},{key:"_internalAbort",value:function(){this._xhr&&(this._xhr.onreadystatechange=null,this._xhr.onprogress=null,this._xhr.onload=null,this._xhr.onerror=null,this._xhr.abort(),this._xhr=null)}},{key:"_onReadyStateChange",value:function(e){var t=e.target;if(2===t.readyState){if(void 0!=t.responseURL){var n=this._seekHandler.removeURLParameters(t.responseURL);t.responseURL!==this._currentRequestURL&&n!==this._currentRedirectedURL&&(this._currentRedirectedURL=n,this._onURLRedirect&&this._onURLRedirect(n))}if(t.status>=200&&t.status<=299){if(this._waitForTotalLength)return;this._status=_.LoaderStatus.kBuffering}else{if(this._status=_.LoaderStatus.kError,!this._onError)throw new m.RuntimeException("RangeLoader: Http code invalid, "+t.status+" "+t.statusText);this._onError(_.LoaderErrors.HTTP_STATUS_CODE_INVALID,{code:t.status,msg:t.statusText})}}}},{key:"_onProgress",value:function(e){if(this._status!==_.LoaderStatus.kError){if(null===this._contentLength){var t=!1;if(this._waitForTotalLength){this._waitForTotalLength=!1,this._totalLengthReceived=!0,t=!0;var n=e.total;this._internalAbort(),null!=n&0!==n&&(this._totalLength=n)}if(-1===this._range.to?this._contentLength=this._totalLength-this._range.from:this._contentLength=this._range.to-this._range.from+1,t)return void this._openSubRange();this._onContentLengthKnown&&this._onContentLengthKnown(this._contentLength)}var i=e.loaded-this._lastTimeLoaded;this._lastTimeLoaded=e.loaded,this._speedSampler.addBytes(i)}}},{key:"_normalizeSpeed",value:function(e){var t=this._chunkSizeKBList,n=t.length-1,i=0,r=0,s=n;if(e<t[0])return t[0];for(;r<=s;){if((i=r+Math.floor((s-r)/2))===n||e>=t[i]&&e<t[i+1])return t[i];t[i]<e?r=i+1:s=i-1}}},{key:"_onLoad",value:function(e){if(this._status!==_.LoaderStatus.kError){if(this._waitForTotalLength)return void(this._waitForTotalLength=!1);this._lastTimeLoaded=0;var t=this._speedSampler.lastSecondKBps;if(0===t&&++this._zeroSpeedChunkCount>=3&&(t=this._speedSampler.currentKBps),0!==t){var n=this._normalizeSpeed(t);this._currentSpeedNormalized!==n&&(this._currentSpeedNormalized=n,this._currentChunkSizeKB=n)}var i=e.target.response,r=this._range.from+this._receivedLength;this._receivedLength+=i.byteLength;var s=!1;null!=this._contentLength&&this._receivedLength<this._contentLength?this._openSubRange():s=!0,this._onDataArrival&&this._onDataArrival(i,r,this._receivedLength),s&&(this._status=_.LoaderStatus.kComplete,this._onComplete&&this._onComplete(this._range.from,this._range.from+this._receivedLength-1))}}},{key:"_onXhrError",value:function(e){this._status=_.LoaderStatus.kError;var t=0,n=null;if(this._contentLength&&this._receivedLength>0&&this._receivedLength<this._contentLength?(t=_.LoaderErrors.EARLY_EOF,n={code:-1,msg:"RangeLoader meet Early-Eof"}):(t=_.LoaderErrors.EXCEPTION,n={code:-1,msg:e.constructor.name+" "+e.type}),!this._onError)throw new m.RuntimeException(n.msg);this._onError(t,n)}},{key:"currentSpeed",get:function(){return this._speedSampler.lastSecondKBps}}]),t}(_.BaseLoader);n.default=p},{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24,"./speed-sampler.js":27}],32:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),o=e("events"),u=i(o),l=e("../utils/logger.js"),d=i(l),h=e("../utils/browser.js"),f=i(h),c=e("./player-events.js"),_=i(c),m=e("../core/transmuxer.js"),p=i(m),v=e("../core/transmuxing-events.js"),g=i(v),y=e("../core/mse-controller.js"),E=i(y),b=e("../core/mse-events.js"),S=i(b),k=e("./player-errors.js"),L=e("../config.js"),R=e("../utils/exception.js"),A=function(){function e(t,n){if(r(this,e),this.TAG="FlvPlayer",this._type="FlvPlayer",this._emitter=new u.default,this._config=(0,L.createDefaultConfig)(),"object"===(void 0===n?"undefined":s(n))&&Object.assign(this._config,n),"flv"!==t.type.toLowerCase())throw new R.InvalidArgumentException("FlvPlayer requires an flv MediaDataSource input!");!0===t.isLive&&(this._config.isLive=!0),this.e={onvLoadedMetadata:this._onvLoadedMetadata.bind(this),onvSeeking:this._onvSeeking.bind(this),onvCanPlay:this._onvCanPlay.bind(this),onvStalled:this._onvStalled.bind(this),onvProgress:this._onvProgress.bind(this)},self.performance&&self.performance.now?this._now=self.performance.now.bind(self.performance):this._now=Date.now,this._pendingSeekTime=null,this._requestSetTime=!1,this._seekpointRecord=null,this._progressChecker=null,this._mediaDataSource=t,this._mediaElement=null,this._msectl=null,this._transmuxer=null,this._mseSourceOpened=!1,this._hasPendingLoad=!1,this._receivedCanPlay=!1,this._mediaInfo=null,this._statisticsInfo=null;var i=f.default.chrome&&(f.default.version.major<50||50===f.default.version.major&&f.default.version.build<2661);this._alwaysSeekKeyframe=!!(i||f.default.msedge||f.default.msie),this._alwaysSeekKeyframe&&(this._config.accurateSeek=!1)}return a(e,[{key:"destroy",value:function(){null!=this._progressChecker&&(window.clearInterval(this._progressChecker),this._progressChecker=null),this._transmuxer&&this.unload(),this._mediaElement&&this.detachMediaElement(),this.e=null,this._mediaDataSource=null,this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){var n=this;e===_.default.MEDIA_INFO?null!=this._mediaInfo&&Promise.resolve().then(function(){n._emitter.emit(_.default.MEDIA_INFO,n.mediaInfo)}):e===_.default.STATISTICS_INFO&&null!=this._statisticsInfo&&Promise.resolve().then(function(){n._emitter.emit(_.default.STATISTICS_INFO,n.statisticsInfo)}),this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{ | |
| 17 | + key:"attachMediaElement",value:function(e){var t=this;if(this._mediaElement=e,e.addEventListener("loadedmetadata",this.e.onvLoadedMetadata),e.addEventListener("seeking",this.e.onvSeeking),e.addEventListener("canplay",this.e.onvCanPlay),e.addEventListener("stalled",this.e.onvStalled),e.addEventListener("progress",this.e.onvProgress),this._msectl=new E.default(this._config),this._msectl.on(S.default.UPDATE_END,this._onmseUpdateEnd.bind(this)),this._msectl.on(S.default.BUFFER_FULL,this._onmseBufferFull.bind(this)),this._msectl.on(S.default.SOURCE_OPEN,function(){t._mseSourceOpened=!0,t._hasPendingLoad&&(t._hasPendingLoad=!1,t.load())}),this._msectl.on(S.default.ERROR,function(e){t._emitter.emit(_.default.ERROR,k.ErrorTypes.MEDIA_ERROR,k.ErrorDetails.MEDIA_MSE_ERROR,e)}),this._msectl.attachMediaElement(e),null!=this._pendingSeekTime)try{e.currentTime=this._pendingSeekTime,this._pendingSeekTime=null}catch(e){}}},{key:"detachMediaElement",value:function(){this._mediaElement&&(this._msectl.detachMediaElement(),this._mediaElement.removeEventListener("loadedmetadata",this.e.onvLoadedMetadata),this._mediaElement.removeEventListener("seeking",this.e.onvSeeking),this._mediaElement.removeEventListener("canplay",this.e.onvCanPlay),this._mediaElement.removeEventListener("stalled",this.e.onvStalled),this._mediaElement.removeEventListener("progress",this.e.onvProgress),this._mediaElement=null),this._msectl&&(this._msectl.destroy(),this._msectl=null)}},{key:"load",value:function(){var e=this;if(!this._mediaElement)throw new R.IllegalStateException("HTMLMediaElement must be attached before load()!");if(this._transmuxer)throw new R.IllegalStateException("FlvPlayer.load() has been called, please call unload() first!");if(!this._hasPendingLoad){if(this._config.deferLoadAfterSourceOpen&&!1===this._mseSourceOpened)return void(this._hasPendingLoad=!0);this._mediaElement.readyState>0&&(this._requestSetTime=!0,this._mediaElement.currentTime=0),this._transmuxer=new p.default(this._mediaDataSource,this._config),this._transmuxer.on(g.default.INIT_SEGMENT,function(t,n){e._msectl.appendInitSegment(n)}),this._transmuxer.on(g.default.MEDIA_SEGMENT,function(t,n){if(e._msectl.appendMediaSegment(n),e._config.lazyLoad&&!e._config.isLive){var i=e._mediaElement.currentTime;n.info.endDts>=1e3*(i+e._config.lazyLoadMaxDuration)&&null==e._progressChecker&&(d.default.v(e.TAG,"Maximum buffering duration exceeded, suspend transmuxing task"),e._suspendTransmuxer())}}),this._transmuxer.on(g.default.LOADING_COMPLETE,function(){e._msectl.endOfStream(),e._emitter.emit(_.default.LOADING_COMPLETE)}),this._transmuxer.on(g.default.RECOVERED_EARLY_EOF,function(){e._emitter.emit(_.default.RECOVERED_EARLY_EOF)}),this._transmuxer.on(g.default.IO_ERROR,function(t,n){e._emitter.emit(_.default.ERROR,k.ErrorTypes.NETWORK_ERROR,t,n)}),this._transmuxer.on(g.default.DEMUX_ERROR,function(t,n){e._emitter.emit(_.default.ERROR,k.ErrorTypes.MEDIA_ERROR,t,{code:-1,msg:n})}),this._transmuxer.on(g.default.MEDIA_INFO,function(t){e._mediaInfo=t,e._emitter.emit(_.default.MEDIA_INFO,Object.assign({},t))}),this._transmuxer.on(g.default.METADATA_ARRIVED,function(t){e._emitter.emit(_.default.METADATA_ARRIVED,t)}),this._transmuxer.on(g.default.SCRIPTDATA_ARRIVED,function(t){e._emitter.emit(_.default.SCRIPTDATA_ARRIVED,t)}),this._transmuxer.on(g.default.STATISTICS_INFO,function(t){e._statisticsInfo=e._fillStatisticsInfo(t),e._emitter.emit(_.default.STATISTICS_INFO,Object.assign({},e._statisticsInfo))}),this._transmuxer.on(g.default.RECOMMEND_SEEKPOINT,function(t){e._mediaElement&&!e._config.accurateSeek&&(e._requestSetTime=!0,e._mediaElement.currentTime=t/1e3)}),this._transmuxer.open()}}},{key:"unload",value:function(){this._mediaElement&&this._mediaElement.pause(),this._msectl&&this._msectl.seek(0),this._transmuxer&&(this._transmuxer.close(),this._transmuxer.destroy(),this._transmuxer=null)}},{key:"play",value:function(){return this._mediaElement.play()}},{key:"pause",value:function(){this._mediaElement.pause()}},{key:"_fillStatisticsInfo",value:function(e){if(e.playerType=this._type,!(this._mediaElement instanceof HTMLVideoElement))return e;var t=!0,n=0,i=0;if(this._mediaElement.getVideoPlaybackQuality){var r=this._mediaElement.getVideoPlaybackQuality();n=r.totalVideoFrames,i=r.droppedVideoFrames}else void 0!=this._mediaElement.webkitDecodedFrameCount?(n=this._mediaElement.webkitDecodedFrameCount,i=this._mediaElement.webkitDroppedFrameCount):t=!1;return t&&(e.decodedFrames=n,e.droppedFrames=i),e}},{key:"_onmseUpdateEnd",value:function(){if(this._config.lazyLoad&&!this._config.isLive){for(var e=this._mediaElement.buffered,t=this._mediaElement.currentTime,n=0,i=0;i<e.length;i++){var r=e.start(i),s=e.end(i);if(r<=t&&t<s){r,n=s;break}}n>=t+this._config.lazyLoadMaxDuration&&null==this._progressChecker&&(d.default.v(this.TAG,"Maximum buffering duration exceeded, suspend transmuxing task"),this._suspendTransmuxer())}}},{key:"_onmseBufferFull",value:function(){d.default.v(this.TAG,"MSE SourceBuffer is full, suspend transmuxing task"),null==this._progressChecker&&this._suspendTransmuxer()}},{key:"_suspendTransmuxer",value:function(){this._transmuxer&&(this._transmuxer.pause(),null==this._progressChecker&&(this._progressChecker=window.setInterval(this._checkProgressAndResume.bind(this),1e3)))}},{key:"_checkProgressAndResume",value:function(){for(var e=this._mediaElement.currentTime,t=this._mediaElement.buffered,n=!1,i=0;i<t.length;i++){var r=t.start(i),s=t.end(i);if(e>=r&&e<s){e>=s-this._config.lazyLoadRecoverDuration&&(n=!0);break}}n&&(window.clearInterval(this._progressChecker),this._progressChecker=null,n&&(d.default.v(this.TAG,"Continue loading from paused position"),this._transmuxer.resume()))}},{key:"_isTimepointBuffered",value:function(e){for(var t=this._mediaElement.buffered,n=0;n<t.length;n++){var i=t.start(n),r=t.end(n);if(e>=i&&e<r)return!0}return!1}},{key:"_internalSeek",value:function(e){var t=this._isTimepointBuffered(e),n=!1,i=0;if(e<1&&this._mediaElement.buffered.length>0){var r=this._mediaElement.buffered.start(0);(r<1&&e<r||f.default.safari)&&(n=!0,i=f.default.safari?.1:r)}if(n)this._requestSetTime=!0,this._mediaElement.currentTime=i;else if(t){if(this._alwaysSeekKeyframe){var s=this._msectl.getNearestKeyframe(Math.floor(1e3*e));this._requestSetTime=!0,this._mediaElement.currentTime=null!=s?s.dts/1e3:e}else this._requestSetTime=!0,this._mediaElement.currentTime=e;null!=this._progressChecker&&this._checkProgressAndResume()}else null!=this._progressChecker&&(window.clearInterval(this._progressChecker),this._progressChecker=null),this._msectl.seek(e),this._transmuxer.seek(Math.floor(1e3*e)),this._config.accurateSeek&&(this._requestSetTime=!0,this._mediaElement.currentTime=e)}},{key:"_checkAndApplyUnbufferedSeekpoint",value:function(){if(this._seekpointRecord)if(this._seekpointRecord.recordTime<=this._now()-100){var e=this._mediaElement.currentTime;this._seekpointRecord=null,this._isTimepointBuffered(e)||(null!=this._progressChecker&&(window.clearTimeout(this._progressChecker),this._progressChecker=null),this._msectl.seek(e),this._transmuxer.seek(Math.floor(1e3*e)),this._config.accurateSeek&&(this._requestSetTime=!0,this._mediaElement.currentTime=e))}else window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this),50)}},{key:"_checkAndResumeStuckPlayback",value:function(e){var t=this._mediaElement;if(e||!this._receivedCanPlay||t.readyState<2){var n=t.buffered;n.length>0&&t.currentTime<n.start(0)&&(d.default.w(this.TAG,"Playback seems stuck at "+t.currentTime+", seek to "+n.start(0)),this._requestSetTime=!0,this._mediaElement.currentTime=n.start(0),this._mediaElement.removeEventListener("progress",this.e.onvProgress))}else this._mediaElement.removeEventListener("progress",this.e.onvProgress)}},{key:"_onvLoadedMetadata",value:function(e){null!=this._pendingSeekTime&&(this._mediaElement.currentTime=this._pendingSeekTime,this._pendingSeekTime=null)}},{key:"_onvSeeking",value:function(e){var t=this._mediaElement.currentTime,n=this._mediaElement.buffered;if(this._requestSetTime)return void(this._requestSetTime=!1);if(t<1&&n.length>0){var i=n.start(0);if(i<1&&t<i||f.default.safari)return this._requestSetTime=!0,void(this._mediaElement.currentTime=f.default.safari?.1:i)}if(this._isTimepointBuffered(t)){if(this._alwaysSeekKeyframe){var r=this._msectl.getNearestKeyframe(Math.floor(1e3*t));null!=r&&(this._requestSetTime=!0,this._mediaElement.currentTime=r.dts/1e3)}return void(null!=this._progressChecker&&this._checkProgressAndResume())}this._seekpointRecord={seekPoint:t,recordTime:this._now()},window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this),50)}},{key:"_onvCanPlay",value:function(e){this._receivedCanPlay=!0,this._mediaElement.removeEventListener("canplay",this.e.onvCanPlay)}},{key:"_onvStalled",value:function(e){this._checkAndResumeStuckPlayback(!0)}},{key:"_onvProgress",value:function(e){this._checkAndResumeStuckPlayback()}},{key:"type",get:function(){return this._type}},{key:"buffered",get:function(){return this._mediaElement.buffered}},{key:"duration",get:function(){return this._mediaElement.duration}},{key:"volume",get:function(){return this._mediaElement.volume},set:function(e){this._mediaElement.volume=e}},{key:"muted",get:function(){return this._mediaElement.muted},set:function(e){this._mediaElement.muted=e}},{key:"currentTime",get:function(){return this._mediaElement?this._mediaElement.currentTime:0},set:function(e){this._mediaElement?this._internalSeek(e):this._pendingSeekTime=e}},{key:"mediaInfo",get:function(){return Object.assign({},this._mediaInfo)}},{key:"statisticsInfo",get:function(){return null==this._statisticsInfo&&(this._statisticsInfo={}),this._statisticsInfo=this._fillStatisticsInfo(this._statisticsInfo),Object.assign({},this._statisticsInfo)}}]),e}();n.default=A},{"../config.js":5,"../core/mse-controller.js":9,"../core/mse-events.js":10,"../core/transmuxer.js":11,"../core/transmuxing-events.js":13,"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./player-errors.js":34,"./player-events.js":35,events:2}],33:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),o=e("events"),u=i(o),l=e("./player-events.js"),d=i(l),h=e("../config.js"),f=e("../utils/exception.js"),c=function(){function e(t,n){if(r(this,e),this.TAG="NativePlayer",this._type="NativePlayer",this._emitter=new u.default,this._config=(0,h.createDefaultConfig)(),"object"===(void 0===n?"undefined":s(n))&&Object.assign(this._config,n),"flv"===t.type.toLowerCase())throw new f.InvalidArgumentException("NativePlayer does't support flv MediaDataSource input!");if(t.hasOwnProperty("segments"))throw new f.InvalidArgumentException("NativePlayer("+t.type+") doesn't support multipart playback!");this.e={onvLoadedMetadata:this._onvLoadedMetadata.bind(this)},this._pendingSeekTime=null,this._statisticsReporter=null,this._mediaDataSource=t,this._mediaElement=null}return a(e,[{key:"destroy",value:function(){this._mediaElement&&(this.unload(),this.detachMediaElement()),this.e=null,this._mediaDataSource=null,this._emitter.removeAllListeners(),this._emitter=null}},{key:"on",value:function(e,t){var n=this;e===d.default.MEDIA_INFO?null!=this._mediaElement&&0!==this._mediaElement.readyState&&Promise.resolve().then(function(){n._emitter.emit(d.default.MEDIA_INFO,n.mediaInfo)}):e===d.default.STATISTICS_INFO&&null!=this._mediaElement&&0!==this._mediaElement.readyState&&Promise.resolve().then(function(){n._emitter.emit(d.default.STATISTICS_INFO,n.statisticsInfo)}),this._emitter.addListener(e,t)}},{key:"off",value:function(e,t){this._emitter.removeListener(e,t)}},{key:"attachMediaElement",value:function(e){if(this._mediaElement=e,e.addEventListener("loadedmetadata",this.e.onvLoadedMetadata),null!=this._pendingSeekTime)try{e.currentTime=this._pendingSeekTime,this._pendingSeekTime=null}catch(e){}}},{key:"detachMediaElement",value:function(){this._mediaElement&&(this._mediaElement.src="",this._mediaElement.removeAttribute("src"),this._mediaElement.removeEventListener("loadedmetadata",this.e.onvLoadedMetadata),this._mediaElement=null),null!=this._statisticsReporter&&(window.clearInterval(this._statisticsReporter),this._statisticsReporter=null)}},{key:"load",value:function(){if(!this._mediaElement)throw new f.IllegalStateException("HTMLMediaElement must be attached before load()!");this._mediaElement.src=this._mediaDataSource.url,this._mediaElement.readyState>0&&(this._mediaElement.currentTime=0),this._mediaElement.preload="auto",this._mediaElement.load(),this._statisticsReporter=window.setInterval(this._reportStatisticsInfo.bind(this),this._config.statisticsInfoReportInterval)}},{key:"unload",value:function(){this._mediaElement&&(this._mediaElement.src="",this._mediaElement.removeAttribute("src")),null!=this._statisticsReporter&&(window.clearInterval(this._statisticsReporter),this._statisticsReporter=null)}},{key:"play",value:function(){return this._mediaElement.play()}},{key:"pause",value:function(){this._mediaElement.pause()}},{key:"_onvLoadedMetadata",value:function(e){null!=this._pendingSeekTime&&(this._mediaElement.currentTime=this._pendingSeekTime,this._pendingSeekTime=null),this._emitter.emit(d.default.MEDIA_INFO,this.mediaInfo)}},{key:"_reportStatisticsInfo",value:function(){this._emitter.emit(d.default.STATISTICS_INFO,this.statisticsInfo)}},{key:"type",get:function(){return this._type}},{key:"buffered",get:function(){return this._mediaElement.buffered}},{key:"duration",get:function(){return this._mediaElement.duration}},{key:"volume",get:function(){return this._mediaElement.volume},set:function(e){this._mediaElement.volume=e}},{key:"muted",get:function(){return this._mediaElement.muted},set:function(e){this._mediaElement.muted=e}},{key:"currentTime",get:function(){return this._mediaElement?this._mediaElement.currentTime:0},set:function(e){this._mediaElement?this._mediaElement.currentTime=e:this._pendingSeekTime=e}},{key:"mediaInfo",get:function(){var e=this._mediaElement instanceof HTMLAudioElement?"audio/":"video/",t={mimeType:e+this._mediaDataSource.type};return this._mediaElement&&(t.duration=Math.floor(1e3*this._mediaElement.duration),this._mediaElement instanceof HTMLVideoElement&&(t.width=this._mediaElement.videoWidth,t.height=this._mediaElement.videoHeight)),t}},{key:"statisticsInfo",get:function(){var e={playerType:this._type,url:this._mediaDataSource.url};if(!(this._mediaElement instanceof HTMLVideoElement))return e;var t=!0,n=0,i=0;if(this._mediaElement.getVideoPlaybackQuality){var r=this._mediaElement.getVideoPlaybackQuality();n=r.totalVideoFrames,i=r.droppedVideoFrames}else void 0!=this._mediaElement.webkitDecodedFrameCount?(n=this._mediaElement.webkitDecodedFrameCount,i=this._mediaElement.webkitDroppedFrameCount):t=!1;return t&&(e.decodedFrames=n,e.droppedFrames=i),e}}]),e}();n.default=c},{"../config.js":5,"../utils/exception.js":40,"./player-events.js":35,events:2}],34:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.ErrorDetails=n.ErrorTypes=void 0;var i=e("../io/loader.js"),r=e("../demux/demux-errors.js"),s=function(e){return e&&e.__esModule?e:{default:e}}(r);n.ErrorTypes={NETWORK_ERROR:"NetworkError",MEDIA_ERROR:"MediaError",OTHER_ERROR:"OtherError"},n.ErrorDetails={NETWORK_EXCEPTION:i.LoaderErrors.EXCEPTION,NETWORK_STATUS_CODE_INVALID:i.LoaderErrors.HTTP_STATUS_CODE_INVALID,NETWORK_TIMEOUT:i.LoaderErrors.CONNECTING_TIMEOUT,NETWORK_UNRECOVERABLE_EARLY_EOF:i.LoaderErrors.UNRECOVERABLE_EARLY_EOF,MEDIA_MSE_ERROR:"MediaMSEError",MEDIA_FORMAT_ERROR:s.default.FORMAT_ERROR,MEDIA_FORMAT_UNSUPPORTED:s.default.FORMAT_UNSUPPORTED,MEDIA_CODEC_UNSUPPORTED:s.default.CODEC_UNSUPPORTED}},{"../demux/demux-errors.js":16,"../io/loader.js":24}],35:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={ERROR:"error",LOADING_COMPLETE:"loading_complete",RECOVERED_EARLY_EOF:"recovered_early_eof",MEDIA_INFO:"media_info",METADATA_ARRIVED:"metadata_arrived",SCRIPTDATA_ARRIVED:"scriptdata_arrived",STATISTICS_INFO:"statistics_info"};n.default=i},{}],36:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(){i(this,e)}return r(e,null,[{key:"getSilentFrame",value:function(e,t){if("mp4a.40.2"===e){if(1===t)return new Uint8Array([0,200,0,128,35,128]);if(2===t)return new Uint8Array([33,0,73,144,2,25,0,35,128]);if(3===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,142]);if(4===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,128,44,128,8,2,56]);if(5===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,56]);if(6===t)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,0,178,0,32,8,224])}else{if(1===t)return new Uint8Array([1,64,34,128,163,78,230,128,186,8,0,0,0,28,6,241,193,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(2===t)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(3===t)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94])}return null}}]),e}();n.default=s},{}],37:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function e(){i(this,e)}return r(e,null,[{key:"init",value:function(){e.types={avc1:[],avcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],mvex:[],mvhd:[],sdtp:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[],smhd:[],".mp3":[]};for(var t in e.types)e.types.hasOwnProperty(t)&&(e.types[t]=[t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2),t.charCodeAt(3)]);var n=e.constants={};n.FTYP=new Uint8Array([105,115,111,109,0,0,0,1,105,115,111,109,97,118,99,49]),n.STSD_PREFIX=new Uint8Array([0,0,0,0,0,0,0,1]),n.STTS=new Uint8Array([0,0,0,0,0,0,0,0]),n.STSC=n.STCO=n.STTS,n.STSZ=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),n.HDLR_VIDEO=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),n.HDLR_AUDIO=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]),n.DREF=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),n.SMHD=new Uint8Array([0,0,0,0,0,0,0,0]),n.VMHD=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0])}},{key:"box",value:function(e){for(var t=8,n=null,i=Array.prototype.slice.call(arguments,1),r=i.length,s=0;s<r;s++)t+=i[s].byteLength;n=new Uint8Array(t),n[0]=t>>>24&255,n[1]=t>>>16&255,n[2]=t>>>8&255,n[3]=255&t,n.set(e,4);for(var a=8,o=0;o<r;o++)n.set(i[o],a),a+=i[o].byteLength;return n}},{key:"generateInitSegment",value:function(t){var n=e.box(e.types.ftyp,e.constants.FTYP),i=e.moov(t),r=new Uint8Array(n.byteLength+i.byteLength);return r.set(n,0),r.set(i,n.byteLength),r}},{key:"moov",value:function(t){var n=e.mvhd(t.timescale,t.duration),i=e.trak(t),r=e.mvex(t);return e.box(e.types.moov,n,i,r)}},{key:"mvhd",value:function(t,n){return e.box(e.types.mvhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t,n>>>24&255,n>>>16&255,n>>>8&255,255&n,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]))}},{key:"trak",value:function(t){return e.box(e.types.trak,e.tkhd(t),e.mdia(t))}},{key:"tkhd",value:function(t){var n=t.id,i=t.duration,r=t.presentWidth,s=t.presentHeight;return e.box(e.types.tkhd,new Uint8Array([0,0,0,7,0,0,0,0,0,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n,0,0,0,0,i>>>24&255,i>>>16&255,i>>>8&255,255&i,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,r>>>8&255,255&r,0,0,s>>>8&255,255&s,0,0]))}},{key:"mdia",value:function(t){return e.box(e.types.mdia,e.mdhd(t),e.hdlr(t),e.minf(t))}},{key:"mdhd",value:function(t){var n=t.timescale,i=t.duration;return e.box(e.types.mdhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n,i>>>24&255,i>>>16&255,i>>>8&255,255&i,85,196,0,0]))}},{key:"hdlr",value:function(t){var n=null;return n="audio"===t.type?e.constants.HDLR_AUDIO:e.constants.HDLR_VIDEO,e.box(e.types.hdlr,n)}},{key:"minf",value:function(t){var n=null;return n="audio"===t.type?e.box(e.types.smhd,e.constants.SMHD):e.box(e.types.vmhd,e.constants.VMHD),e.box(e.types.minf,n,e.dinf(),e.stbl(t))}},{key:"dinf",value:function(){return e.box(e.types.dinf,e.box(e.types.dref,e.constants.DREF))}},{key:"stbl",value:function(t){return e.box(e.types.stbl,e.stsd(t),e.box(e.types.stts,e.constants.STTS),e.box(e.types.stsc,e.constants.STSC),e.box(e.types.stsz,e.constants.STSZ),e.box(e.types.stco,e.constants.STCO))}},{key:"stsd",value:function(t){return"audio"===t.type?"mp3"===t.codec?e.box(e.types.stsd,e.constants.STSD_PREFIX,e.mp3(t)):e.box(e.types.stsd,e.constants.STSD_PREFIX,e.mp4a(t)):e.box(e.types.stsd,e.constants.STSD_PREFIX,e.avc1(t))}},{key:"mp3",value:function(t){var n=t.channelCount,i=t.audioSampleRate,r=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,n,0,16,0,0,0,0,i>>>8&255,255&i,0,0]);return e.box(e.types[".mp3"],r)}},{key:"mp4a",value:function(t){var n=t.channelCount,i=t.audioSampleRate,r=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,n,0,16,0,0,0,0,i>>>8&255,255&i,0,0]);return e.box(e.types.mp4a,r,e.esds(t))}},{key:"esds",value:function(t){var n=t.config||[],i=n.length,r=new Uint8Array([0,0,0,0,3,23+i,0,1,0,4,15+i,64,21,0,0,0,0,0,0,0,0,0,0,0,5].concat([i]).concat(n).concat([6,1,2]));return e.box(e.types.esds,r)}},{key:"avc1",value:function(t){var n=t.avcc,i=t.codecWidth,r=t.codecHeight,s=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,i>>>8&255,255&i,r>>>8&255,255&r,0,72,0,0,0,72,0,0,0,0,0,0,0,1,10,120,113,113,47,102,108,118,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,255,255]);return e.box(e.types.avc1,s,e.box(e.types.avcC,n))}},{key:"mvex",value:function(t){return e.box(e.types.mvex,e.trex(t))}},{key:"trex",value:function(t){var n=t.id,i=new Uint8Array([0,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]);return e.box(e.types.trex,i)}},{key:"moof",value:function(t,n){return e.box(e.types.moof,e.mfhd(t.sequenceNumber),e.traf(t,n))}},{key:"mfhd",value:function(t){var n=new Uint8Array([0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t]);return e.box(e.types.mfhd,n)}},{key:"traf",value:function(t,n){var i=t.id,r=e.box(e.types.tfhd,new Uint8Array([0,0,0,0,i>>>24&255,i>>>16&255,i>>>8&255,255&i])),s=e.box(e.types.tfdt,new Uint8Array([0,0,0,0,n>>>24&255,n>>>16&255,n>>>8&255,255&n])),a=e.sdtp(t),o=e.trun(t,a.byteLength+16+16+8+16+8+8);return e.box(e.types.traf,r,s,o,a)}},{key:"sdtp",value:function(t){for(var n=t.samples||[],i=n.length,r=new Uint8Array(4+i),s=0;s<i;s++){var a=n[s].flags;r[s+4]=a.isLeading<<6|a.dependsOn<<4|a.isDependedOn<<2|a.hasRedundancy}return e.box(e.types.sdtp,r)}},{key:"trun",value:function(t,n){var i=t.samples||[],r=i.length,s=12+16*r,a=new Uint8Array(s);n+=8+s,a.set([0,0,15,1,r>>>24&255,r>>>16&255,r>>>8&255,255&r,n>>>24&255,n>>>16&255,n>>>8&255,255&n],0);for(var o=0;o<r;o++){var u=i[o].duration,l=i[o].size,d=i[o].flags,h=i[o].cts;a.set([u>>>24&255,u>>>16&255,u>>>8&255,255&u,l>>>24&255,l>>>16&255,l>>>8&255,255&l,d.isLeading<<2|d.dependsOn,d.isDependedOn<<6|d.hasRedundancy<<4|d.isNonSync,0,0,h>>>24&255,h>>>16&255,h>>>8&255,255&h],12+16*o)}return e.box(e.types.trun,a)}},{key:"mdat",value:function(t){return e.box(e.types.mdat,t)}}]),e}();s.init(),n.default=s},{}],38:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("../utils/logger.js"),o=i(a),u=e("./mp4-generator.js"),l=i(u),d=e("./aac-silent.js"),h=i(d),f=e("../utils/browser.js"),c=i(f),_=e("../core/media-segment-info.js"),m=e("../utils/exception.js"),p=function(){function e(t){r(this,e),this.TAG="MP4Remuxer",this._config=t,this._isLive=!0===t.isLive,this._dtsBase=-1,this._dtsBaseInited=!1,this._audioDtsBase=1/0,this._videoDtsBase=1/0,this._audioNextDts=void 0,this._videoNextDts=void 0,this._audioStashedLastSample=null,this._videoStashedLastSample=null,this._audioMeta=null,this._videoMeta=null,this._audioSegmentInfoList=new _.MediaSegmentInfoList("audio"),this._videoSegmentInfoList=new _.MediaSegmentInfoList("video"),this._onInitSegment=null,this._onMediaSegment=null,this._forceFirstIDR=!(!c.default.chrome||!(c.default.version.major<50||50===c.default.version.major&&c.default.version.build<2661)),this._fillSilentAfterSeek=c.default.msedge||c.default.msie,this._mp3UseMpegAudio=!c.default.firefox,this._fillAudioTimestampGap=this._config.fixAudioTimestampGap}return s(e,[{key:"destroy",value:function(){this._dtsBase=-1,this._dtsBaseInited=!1,this._audioMeta=null,this._videoMeta=null,this._audioSegmentInfoList.clear(),this._audioSegmentInfoList=null,this._videoSegmentInfoList.clear(),this._videoSegmentInfoList=null,this._onInitSegment=null,this._onMediaSegment=null}},{key:"bindDataSource",value:function(e){return e.onDataAvailable=this.remux.bind(this),e.onTrackMetadata=this._onTrackMetadataReceived.bind(this),this}},{key:"insertDiscontinuity",value:function(){this._audioNextDts=this._videoNextDts=void 0}},{key:"seek",value:function(e){this._audioStashedLastSample=null,this._videoStashedLastSample=null,this._videoSegmentInfoList.clear(),this._audioSegmentInfoList.clear()}},{key:"remux",value:function(e,t){if(!this._onMediaSegment)throw new m.IllegalStateException("MP4Remuxer: onMediaSegment callback must be specificed!");this._dtsBaseInited||this._calculateDtsBase(e,t),this._remuxVideo(t),this._remuxAudio(e)}},{key:"_onTrackMetadataReceived",value:function(e,t){var n=null,i="mp4",r=t.codec;if("audio"===e)this._audioMeta=t,"mp3"===t.codec&&this._mp3UseMpegAudio?(i="mpeg",r="",n=new Uint8Array):n=l.default.generateInitSegment(t);else{if("video"!==e)return;this._videoMeta=t,n=l.default.generateInitSegment(t)}if(!this._onInitSegment)throw new m.IllegalStateException("MP4Remuxer: onInitSegment callback must be specified!");this._onInitSegment(e,{type:e,data:n.buffer,codec:r,container:e+"/"+i,mediaDuration:t.duration})}},{key:"_calculateDtsBase",value:function(e,t){this._dtsBaseInited||(e.samples&&e.samples.length&&(this._audioDtsBase=e.samples[0].dts),t.samples&&t.samples.length&&(this._videoDtsBase=t.samples[0].dts),this._dtsBase=Math.min(this._audioDtsBase,this._videoDtsBase),this._dtsBaseInited=!0)}},{key:"flushStashedSamples",value:function(){var e=this._videoStashedLastSample,t=this._audioStashedLastSample,n={type:"video",id:1,sequenceNumber:0,samples:[],length:0};null!=e&&(n.samples.push(e),n.length=e.length);var i={type:"audio",id:2,sequenceNumber:0,samples:[],length:0};null!=t&&(i.samples.push(t),i.length=t.length),this._videoStashedLastSample=null,this._audioStashedLastSample=null,this._remuxVideo(n,!0),this._remuxAudio(i,!0)}},{key:"_remuxAudio",value:function(e,t){if(null!=this._audioMeta){var n=e,i=n.samples,r=void 0,s=-1,a=-1,u=this._audioMeta.refSampleDuration,d="mp3"===this._audioMeta.codec&&this._mp3UseMpegAudio,f=this._dtsBaseInited&&void 0===this._audioNextDts,m=!1;if(i&&0!==i.length&&(1!==i.length||t)){var p=0,v=null,g=0;d?(p=0,g=n.length):(p=8,g=8+n.length);var y=null;if(i.length>1&&(y=i.pop(),g-=y.length),null!=this._audioStashedLastSample){var E=this._audioStashedLastSample;this._audioStashedLastSample=null,i.unshift(E),g+=E.length}null!=y&&(this._audioStashedLastSample=y);var b=i[0].dts-this._dtsBase;if(this._audioNextDts)r=b-this._audioNextDts;else if(this._audioSegmentInfoList.isEmpty())r=0,this._fillSilentAfterSeek&&!this._videoSegmentInfoList.isEmpty()&&"mp3"!==this._audioMeta.originalCodec&&(m=!0);else{var S=this._audioSegmentInfoList.getLastSampleBefore(b);if(null!=S){var k=b-(S.originalDts+S.duration);k<=3&&(k=0);var L=S.dts+S.duration+k;r=b-L}else r=0}if(m){var R=b-r,A=this._videoSegmentInfoList.getLastSegmentBefore(b);if(null!=A&&A.beginDts<R){var w=h.default.getSilentFrame(this._audioMeta.originalCodec,this._audioMeta.channelCount);if(w){var T=A.beginDts,O=R-A.beginDts;o.default.v(this.TAG,"InsertPrefixSilentAudio: dts: "+T+", duration: "+O),i.unshift({unit:w,dts:T,pts:T}),g+=w.byteLength}}else m=!1}for(var C=[],I=0;I<i.length;I++){var D=i[I],x=D.unit,M=D.dts-this._dtsBase,B=M-r;-1===s&&(s=B);var j=0;if(I!==i.length-1){j=i[I+1].dts-this._dtsBase-r-B}else if(null!=y){var P=y.dts-this._dtsBase-r;j=P-B}else j=C.length>=1?C[C.length-1].duration:Math.floor(u);var U=!1,N=null;if(j>1.5*u&&"mp3"!==this._audioMeta.codec&&this._fillAudioTimestampGap&&!c.default.safari){U=!0;var F=Math.abs(j-u),G=Math.ceil(F/u),V=B+u;o.default.w(this.TAG,"Large audio timestamp gap detected, may cause AV sync to drift. Silent frames will be generated to avoid unsync.\ndts: "+(B+j)+" ms, expected: "+(B+Math.round(u))+" ms, delta: "+Math.round(F)+" ms, generate: "+G+" frames");var z=h.default.getSilentFrame(this._audioMeta.originalCodec,this._audioMeta.channelCount);null==z&&(o.default.w(this.TAG,"Unable to generate silent frame for "+this._audioMeta.originalCodec+" with "+this._audioMeta.channelCount+" channels, repeat last frame"),z=x),N=[];for(var H=0;H<G;H++){var K=Math.round(V);if(N.length>0){var q=N[N.length-1];q.duration=K-q.dts}var W={dts:K,pts:K,cts:0,unit:z,size:z.byteLength,duration:0,originalDts:M,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0}};N.push(W),g+=W.size,V+=u}var X=N[N.length-1];X.duration=B+j-X.dts,j=Math.round(u)}C.push({dts:B,pts:B,cts:0,unit:D.unit,size:D.unit.byteLength,duration:j,originalDts:M,flags:{isLeading:0,dependsOn:1,isDependedOn:0,hasRedundancy:0}}),U&&C.push.apply(C,N)}d?v=new Uint8Array(g):(v=new Uint8Array(g),v[0]=g>>>24&255,v[1]=g>>>16&255,v[2]=g>>>8&255,v[3]=255&g,v.set(l.default.types.mdat,4));for(var Y=0;Y<C.length;Y++){var Z=C[Y].unit;v.set(Z,p),p+=Z.byteLength}var Q=C[C.length-1];a=Q.dts+Q.duration,this._audioNextDts=a;var J=new _.MediaSegmentInfo;J.beginDts=s,J.endDts=a,J.beginPts=s,J.endPts=a,J.originalBeginDts=C[0].originalDts,J.originalEndDts=Q.originalDts+Q.duration, | |
| 18 | + J.firstSample=new _.SampleInfo(C[0].dts,C[0].pts,C[0].duration,C[0].originalDts,!1),J.lastSample=new _.SampleInfo(Q.dts,Q.pts,Q.duration,Q.originalDts,!1),this._isLive||this._audioSegmentInfoList.append(J),n.samples=C,n.sequenceNumber++;var $=null;$=d?new Uint8Array:l.default.moof(n,s),n.samples=[],n.length=0;var ee={type:"audio",data:this._mergeBoxes($,v).buffer,sampleCount:C.length,info:J};d&&f&&(ee.timestampOffset=s),this._onMediaSegment("audio",ee)}}}},{key:"_remuxVideo",value:function(e,t){if(null!=this._videoMeta){var n=e,i=n.samples,r=void 0,s=-1,a=-1,o=-1,u=-1;if(i&&0!==i.length&&(1!==i.length||t)){var d=8,h=null,f=8+e.length,c=null;if(i.length>1&&(c=i.pop(),f-=c.length),null!=this._videoStashedLastSample){var m=this._videoStashedLastSample;this._videoStashedLastSample=null,i.unshift(m),f+=m.length}null!=c&&(this._videoStashedLastSample=c);var p=i[0].dts-this._dtsBase;if(this._videoNextDts)r=p-this._videoNextDts;else if(this._videoSegmentInfoList.isEmpty())r=0;else{var v=this._videoSegmentInfoList.getLastSampleBefore(p);if(null!=v){var g=p-(v.originalDts+v.duration);g<=3&&(g=0);var y=v.dts+v.duration+g;r=p-y}else r=0}for(var E=new _.MediaSegmentInfo,b=[],S=0;S<i.length;S++){var k=i[S],L=k.dts-this._dtsBase,R=k.isKeyframe,A=L-r,w=k.cts,T=A+w;-1===s&&(s=A,o=T);var O=0;if(S!==i.length-1){O=i[S+1].dts-this._dtsBase-r-A}else if(null!=c){var C=c.dts-this._dtsBase-r;O=C-A}else O=b.length>=1?b[b.length-1].duration:Math.floor(this._videoMeta.refSampleDuration);if(R){var I=new _.SampleInfo(A,T,O,k.dts,!0);I.fileposition=k.fileposition,E.appendSyncPoint(I)}b.push({dts:A,pts:T,cts:w,units:k.units,size:k.length,isKeyframe:R,duration:O,originalDts:L,flags:{isLeading:0,dependsOn:R?2:1,isDependedOn:R?1:0,hasRedundancy:0,isNonSync:R?0:1}})}h=new Uint8Array(f),h[0]=f>>>24&255,h[1]=f>>>16&255,h[2]=f>>>8&255,h[3]=255&f,h.set(l.default.types.mdat,4);for(var D=0;D<b.length;D++)for(var x=b[D].units;x.length;){var M=x.shift(),B=M.data;h.set(B,d),d+=B.byteLength}var j=b[b.length-1];if(a=j.dts+j.duration,u=j.pts+j.duration,this._videoNextDts=a,E.beginDts=s,E.endDts=a,E.beginPts=o,E.endPts=u,E.originalBeginDts=b[0].originalDts,E.originalEndDts=j.originalDts+j.duration,E.firstSample=new _.SampleInfo(b[0].dts,b[0].pts,b[0].duration,b[0].originalDts,b[0].isKeyframe),E.lastSample=new _.SampleInfo(j.dts,j.pts,j.duration,j.originalDts,j.isKeyframe),this._isLive||this._videoSegmentInfoList.append(E),n.samples=b,n.sequenceNumber++,this._forceFirstIDR){var P=b[0].flags;P.dependsOn=2,P.isNonSync=0}var U=l.default.moof(n,s);n.samples=[],n.length=0,this._onMediaSegment("video",{type:"video",data:this._mergeBoxes(U,h).buffer,sampleCount:b.length,info:E})}}}},{key:"_mergeBoxes",value:function(e,t){var n=new Uint8Array(e.byteLength+t.byteLength);return n.set(e,0),n.set(t,e.byteLength),n}},{key:"onInitSegment",get:function(){return this._onInitSegment},set:function(e){this._onInitSegment=e}},{key:"onMediaSegment",get:function(){return this._onMediaSegment},set:function(e){this._onMediaSegment=e}}]),e}();n.default=p},{"../core/media-segment-info.js":8,"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./aac-silent.js":36,"./mp4-generator.js":37}],39:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i={};!function(){var e=self.navigator.userAgent.toLowerCase(),t=/(edge)\/([\w.]+)/.exec(e)||/(opr)[\/]([\w.]+)/.exec(e)||/(chrome)[ \/]([\w.]+)/.exec(e)||/(iemobile)[\/]([\w.]+)/.exec(e)||/(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("trident")>=0&&/(rv)(?::| )([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(firefox)[ \/]([\w.]+)/.exec(e)||[],n=/(ipad)/.exec(e)||/(ipod)/.exec(e)||/(windows phone)/.exec(e)||/(iphone)/.exec(e)||/(kindle)/.exec(e)||/(android)/.exec(e)||/(windows)/.exec(e)||/(mac)/.exec(e)||/(linux)/.exec(e)||/(cros)/.exec(e)||[],r={browser:t[5]||t[3]||t[1]||"",version:t[2]||t[4]||"0",majorVersion:t[4]||t[2]||"0",platform:n[0]||""},s={};if(r.browser){s[r.browser]=!0;var a=r.majorVersion.split(".");s.version={major:parseInt(r.majorVersion,10),string:r.version},a.length>1&&(s.version.minor=parseInt(a[1],10)),a.length>2&&(s.version.build=parseInt(a[2],10))}r.platform&&(s[r.platform]=!0),(s.chrome||s.opr||s.safari)&&(s.webkit=!0),(s.rv||s.iemobile)&&(s.rv&&delete s.rv,r.browser="msie",s.msie=!0),s.edge&&(delete s.edge,r.browser="msedge",s.msedge=!0),s.opr&&(r.browser="opera",s.opera=!0),s.safari&&s.android&&(r.browser="android",s.android=!0),s.name=r.browser,s.platform=r.platform;for(var o in i)i.hasOwnProperty(o)&&delete i[o];Object.assign(i,s)}(),n.default=i},{}],40:[function(e,t,n){"use strict";function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function r(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),o=n.RuntimeException=function(){function e(t){s(this,e),this._message=t}return a(e,[{key:"toString",value:function(){return this.name+": "+this.message}},{key:"name",get:function(){return"RuntimeException"}},{key:"message",get:function(){return this._message}}]),e}();n.IllegalStateException=function(e){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return r(t,e),a(t,[{key:"name",get:function(){return"IllegalStateException"}}]),t}(o),n.InvalidArgumentException=function(e){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return r(t,e),a(t,[{key:"name",get:function(){return"InvalidArgumentException"}}]),t}(o),n.NotImplementedException=function(e){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return r(t,e),a(t,[{key:"name",get:function(){return"NotImplementedException"}}]),t}(o)},{}],41:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=e("events"),a=function(e){return e&&e.__esModule?e:{default:e}}(s),o=function(){function e(){i(this,e)}return r(e,null,[{key:"e",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","error",i),e.ENABLE_ERROR&&(console.error?console.error(i):console.warn?console.warn(i):console.log(i))}},{key:"i",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","info",i),e.ENABLE_INFO&&(console.info?console.info(i):console.log(i))}},{key:"w",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","warn",i),e.ENABLE_WARN&&(console.warn?console.warn(i):console.log(i))}},{key:"d",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","debug",i),e.ENABLE_DEBUG&&(console.debug?console.debug(i):console.log(i))}},{key:"v",value:function(t,n){t&&!e.FORCE_GLOBAL_TAG||(t=e.GLOBAL_TAG);var i="["+t+"] > "+n;e.ENABLE_CALLBACK&&e.emitter.emit("log","verbose",i),e.ENABLE_VERBOSE&&console.log(i)}}]),e}();o.GLOBAL_TAG="flv.js",o.FORCE_GLOBAL_TAG=!1,o.ENABLE_ERROR=!0,o.ENABLE_INFO=!0,o.ENABLE_WARN=!0,o.ENABLE_DEBUG=!0,o.ENABLE_VERBOSE=!0,o.ENABLE_CALLBACK=!1,o.emitter=new a.default,n.default=o},{events:2}],42:[function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),a=e("events"),o=i(a),u=e("./logger.js"),l=i(u),d=function(){function e(){r(this,e)}return s(e,null,[{key:"getConfig",value:function(){return{globalTag:l.default.GLOBAL_TAG,forceGlobalTag:l.default.FORCE_GLOBAL_TAG,enableVerbose:l.default.ENABLE_VERBOSE,enableDebug:l.default.ENABLE_DEBUG,enableInfo:l.default.ENABLE_INFO,enableWarn:l.default.ENABLE_WARN,enableError:l.default.ENABLE_ERROR,enableCallback:l.default.ENABLE_CALLBACK}}},{key:"applyConfig",value:function(e){l.default.GLOBAL_TAG=e.globalTag,l.default.FORCE_GLOBAL_TAG=e.forceGlobalTag,l.default.ENABLE_VERBOSE=e.enableVerbose,l.default.ENABLE_DEBUG=e.enableDebug,l.default.ENABLE_INFO=e.enableInfo,l.default.ENABLE_WARN=e.enableWarn,l.default.ENABLE_ERROR=e.enableError,l.default.ENABLE_CALLBACK=e.enableCallback}},{key:"_notifyChange",value:function(){var t=e.emitter;if(t.listenerCount("change")>0){var n=e.getConfig();t.emit("change",n)}}},{key:"registerListener",value:function(t){e.emitter.addListener("change",t)}},{key:"removeListener",value:function(t){e.emitter.removeListener("change",t)}},{key:"addLogListener",value:function(t){l.default.emitter.addListener("log",t),l.default.emitter.listenerCount("log")>0&&(l.default.ENABLE_CALLBACK=!0,e._notifyChange())}},{key:"removeLogListener",value:function(t){l.default.emitter.removeListener("log",t),0===l.default.emitter.listenerCount("log")&&(l.default.ENABLE_CALLBACK=!1,e._notifyChange())}},{key:"forceGlobalTag",get:function(){return l.default.FORCE_GLOBAL_TAG},set:function(t){l.default.FORCE_GLOBAL_TAG=t,e._notifyChange()}},{key:"globalTag",get:function(){return l.default.GLOBAL_TAG},set:function(t){l.default.GLOBAL_TAG=t,e._notifyChange()}},{key:"enableAll",get:function(){return l.default.ENABLE_VERBOSE&&l.default.ENABLE_DEBUG&&l.default.ENABLE_INFO&&l.default.ENABLE_WARN&&l.default.ENABLE_ERROR},set:function(t){l.default.ENABLE_VERBOSE=t,l.default.ENABLE_DEBUG=t,l.default.ENABLE_INFO=t,l.default.ENABLE_WARN=t,l.default.ENABLE_ERROR=t,e._notifyChange()}},{key:"enableDebug",get:function(){return l.default.ENABLE_DEBUG},set:function(t){l.default.ENABLE_DEBUG=t,e._notifyChange()}},{key:"enableVerbose",get:function(){return l.default.ENABLE_VERBOSE},set:function(t){l.default.ENABLE_VERBOSE=t,e._notifyChange()}},{key:"enableInfo",get:function(){return l.default.ENABLE_INFO},set:function(t){l.default.ENABLE_INFO=t,e._notifyChange()}},{key:"enableWarn",get:function(){return l.default.ENABLE_WARN},set:function(t){l.default.ENABLE_WARN=t,e._notifyChange()}},{key:"enableError",get:function(){return l.default.ENABLE_ERROR},set:function(t){l.default.ENABLE_ERROR=t,e._notifyChange()}}]),e}();d.emitter=new o.default,n.default=d},{"./logger.js":41,events:2}],43:[function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),s=function(){function t(){i(this,t)}return r(t,null,[{key:"install",value:function(){Object.setPrototypeOf=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},Object.assign=Object.assign||function(e){if(void 0===e||null===e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),n=1;n<arguments.length;n++){var i=arguments[n];if(void 0!==i&&null!==i)for(var r in i)i.hasOwnProperty(r)&&(t[r]=i[r])}return t},"function"!=typeof self.Promise&&e("es6-promise").polyfill()}}]),t}();s.install(),n.default=s},{"es6-promise":1}],44:[function(e,t,n){"use strict";function i(e,t,n){var i=e;if(t+n<i.length){for(;n--;)if(128!=(192&i[++t]))return!1;return!0}return!1}function r(e){for(var t=[],n=e,r=0,s=e.length;r<s;)if(n[r]<128)t.push(String.fromCharCode(n[r])),++r;else{if(n[r]<192);else if(n[r]<224){if(i(n,r,1)){var a=(31&n[r])<<6|63&n[r+1];if(a>=128){t.push(String.fromCharCode(65535&a)),r+=2;continue}}}else if(n[r]<240){if(i(n,r,2)){var o=(15&n[r])<<12|(63&n[r+1])<<6|63&n[r+2];if(o>=2048&&55296!=(63488&o)){t.push(String.fromCharCode(65535&o)),r+=3;continue}}}else if(n[r]<248&&i(n,r,3)){var u=(7&n[r])<<18|(63&n[r+1])<<12|(63&n[r+2])<<6|63&n[r+3];if(u>65536&&u<1114112){u-=65536,t.push(String.fromCharCode(u>>>10|55296)),t.push(String.fromCharCode(1023&u|56320)),r+=4;continue}}t.push(String.fromCharCode(65533)),++r}return t.join("")}Object.defineProperty(n,"__esModule",{value:!0}),n.default=r},{}]},{},[21])(21)}); | |
| 19 | + //# sourceMappingURL=flv.min.js.map | |
| 20 | +</script> | |
| 21 | +<script type="text/javascript"> | |
| 22 | +/** | |
| 23 | + * 创建一个FLV播放器,参数如下: | |
| 24 | + * { | |
| 25 | + * container : 视频容器元素 | |
| 26 | + * muted : 是否静音 | |
| 27 | + * url : HTTP-FLV地址 | |
| 28 | + * } | |
| 29 | + */ | |
| 30 | +function FLVPlayer(opts) | |
| 31 | +{ | |
| 32 | + var videoElement = document.createElement('VIDEO'); | |
| 33 | + videoElement.autoplay = true; | |
| 34 | + videoElement.controls = false; | |
| 35 | + videoElement.muted = false; | |
| 36 | + videoElement.style.width = '100%'; | |
| 37 | + videoElement.style.height = '100%'; | |
| 38 | + opts.container.append(videoElement); | |
| 39 | + | |
| 40 | + this.container = opts.container; | |
| 41 | + this.videoElement = videoElement; | |
| 42 | + this.httpFlvURL = opts.url; | |
| 43 | + | |
| 44 | + this.mediaInfo = null; | |
| 45 | + this.play = null; | |
| 46 | + this.onPlayEvtListener = null; | |
| 47 | + this.onPauseEvtListener = null; | |
| 48 | + this.onStopEvtListener = null; | |
| 49 | + | |
| 50 | + this.autoFastForward = opts.autoFastForward; | |
| 51 | + this.autoFastForwardInterval = null; | |
| 52 | + | |
| 53 | + this.play = function() | |
| 54 | + { | |
| 55 | + if (this.player) return; | |
| 56 | + | |
| 57 | + var self = this; | |
| 58 | + self.player = new flvjs.createPlayer({ | |
| 59 | + type : 'flv', | |
| 60 | + url : self.httpFlvURL, | |
| 61 | + isLive : true, | |
| 62 | + enableWorker : true, | |
| 63 | + enableStashBuffer : true, | |
| 64 | + autoCleanupSourceBuffer : true, | |
| 65 | + autoCleanupMaxBackwardDuration : 5, | |
| 66 | + autoCleanupMinBackwardDuration : 1 | |
| 67 | + }); | |
| 68 | + | |
| 69 | + self.player.on('media_info', function() | |
| 70 | + { | |
| 71 | + self.mediaInfo = self.player.mediaInfo; | |
| 72 | + }); | |
| 73 | + | |
| 74 | + self.player.on('statistics_info', function() | |
| 75 | + { | |
| 76 | + console.log(arguments); | |
| 77 | + }); | |
| 78 | + | |
| 79 | + var autoPlayTimer = null; | |
| 80 | + self.videoElement.addEventListener('player', function(e) | |
| 81 | + { | |
| 82 | + if (autoPlayTimer) clearInterval(autoPlayTimer); | |
| 83 | + if (self.onPlayEvtListener) self.onPlayEvtListener(self, e); | |
| 84 | + }); | |
| 85 | + self.videoElement.addEventListener('dblclick', function() | |
| 86 | + { | |
| 87 | + if (self.videoElement.requestFullscreen) self.videoElement.requestFullscreen(); | |
| 88 | + }); | |
| 89 | + autoPlayTimer = setInterval(function() | |
| 90 | + { | |
| 91 | + try { self.player.play(); } catch(e) { clearInterval(autoPlayTimer); }; | |
| 92 | + }); | |
| 93 | + | |
| 94 | + self.player.attachMediaElement(self.videoElement); | |
| 95 | + self.player.load(); | |
| 96 | + self.player.play(); | |
| 97 | + | |
| 98 | + if (this.autoFastForward) this.autoFastForwardInterval = setInterval(function() | |
| 99 | + { | |
| 100 | + if (self.videoElement.buffered.length > 0 && self.videoElement.buffered.end(0) - self.videoElement.currentTime > 2) | |
| 101 | + { | |
| 102 | + console.log(self.videoElement.buffered.end(0) + "-" + self.videoElement.currentTime); | |
| 103 | + self.videoElement.currentTime = self.videoElement.buffered.end(0) - 1; | |
| 104 | + } | |
| 105 | + }, 1000); | |
| 106 | + }; | |
| 107 | + | |
| 108 | + this.fullscreen = function() | |
| 109 | + { | |
| 110 | + if (this.videoElement && this.videoElement.requestFullscreen) | |
| 111 | + this.videoElement.requestFullscreen(); | |
| 112 | + }; | |
| 113 | + | |
| 114 | + this.onPlay = function(fn) | |
| 115 | + { | |
| 116 | + this.onPlayEvtListener = fn; | |
| 117 | + }; | |
| 118 | + | |
| 119 | + this.destroy = function() | |
| 120 | + { | |
| 121 | + this.player.destroy(); | |
| 122 | + clearInterval(this.autoFastForwardInterval); | |
| 123 | + } | |
| 124 | +} | |
| 125 | +</script> | |
| 126 | +<script type="text/javascript"> | |
| 127 | + if (location.hash) | |
| 128 | + { | |
| 129 | + var hash = location.hash.substring(1); | |
| 130 | + $('#tag').val(hash); | |
| 131 | + } | |
| 132 | + function playVideo() | |
| 133 | + { | |
| 134 | + var videoPlayer = new FLVPlayer({ | |
| 135 | + container : $('#xxoo'), | |
| 136 | + url : '/video/' + $('#tag').val(), | |
| 137 | + // 自动快进追祯,但是可能会导致画面停顿 | |
| 138 | + autoFastForward : false | |
| 139 | + }); | |
| 140 | + videoPlayer.play(); | |
| 141 | + } | |
| 142 | +</script> | |
| 143 | +<button onclick="playVideo()">Play Video</button> | |
| 144 | +</body> | |
| 145 | +</html> | ... | ... |
src/main/resources/nginx_sample.conf
0 → 100644
| 1 | +++ a/src/main/resources/nginx_sample.conf | |
| 1 | +# 使用多个域名的模式 | |
| 2 | +# 通过将多个域名都反向代理到音视频服务器的3333端口 | |
| 3 | +# 为单个域名的6路并发,扩展到 n * 6路,每增加一个域名就可以多出6路并发 | |
| 4 | +# 流媒体URL如: | |
| 5 | +# http://v1.hentai.org.cn/video/013800138999-2 | |
| 6 | +# http://v2.hentai.org.cn/video/013800138999-2 | |
| 7 | + | |
| 8 | +server | |
| 9 | +{ | |
| 10 | + listen 80; | |
| 11 | + server_name v1.hentai.org.cn v2.hentai.org.cn v3.hentai.org.cn v4.hentai.org.cn v5.hentai.org.cn v6.hentai.org.cn; | |
| 12 | + location / | |
| 13 | + { | |
| 14 | + proxy_pass http://localhost:3333; | |
| 15 | + chunked_transfer_encoding on; | |
| 16 | + add_header 'Access-Control-Allow-Origin' '*'; | |
| 17 | + add_header 'Access-Control-Allow-Credentials' 'true'; | |
| 18 | + } | |
| 19 | + access_log off; | |
| 20 | +} | |
| 21 | + | |
| 22 | +# -------------------------------------------------- 华丽的分割线 -------------------------------------------------- | |
| 23 | + | |
| 24 | +# 使用多个端口的模式 | |
| 25 | +# 每多一个端口配置,就可以多出6路并发 | |
| 26 | +# 流媒体URL如: | |
| 27 | +# http://192.168.0.2:1000/video/013800138999-2 | |
| 28 | +# http://192.168.0.2:1001/video/013800138999-2 | |
| 29 | +# http://192.168.0.2:1002/video/013800138999-2 | |
| 30 | + | |
| 31 | +server | |
| 32 | +{ | |
| 33 | + listen 1000; | |
| 34 | + location / | |
| 35 | + { | |
| 36 | + proxy_pass http://localhost:3333; | |
| 37 | + chunked_transfer_encoding on; | |
| 38 | + } | |
| 39 | + access_log off; | |
| 40 | +} | |
| 41 | + | |
| 42 | +server | |
| 43 | +{ | |
| 44 | + listen 1001; | |
| 45 | + location / | |
| 46 | + { | |
| 47 | + proxy_pass http://localhost:3333; | |
| 48 | + chunked_transfer_encoding on; | |
| 49 | + } | |
| 50 | + access_log off; | |
| 51 | +} | |
| 52 | + | |
| 53 | +server | |
| 54 | +{ | |
| 55 | + listen 1002; | |
| 56 | + location / | |
| 57 | + { | |
| 58 | + proxy_pass http://localhost:3333; | |
| 59 | + chunked_transfer_encoding on; | |
| 60 | + } | |
| 61 | + access_log off; | |
| 62 | +} | |
| 0 | 63 | \ No newline at end of file | ... | ... |
src/main/resources/tcpdump.bin
0 → 100644
No preview for this file type
src/main/resources/test.html
0 → 100644
| 1 | +++ a/src/main/resources/test.html | |
| 1 | +<!doctype html> | |
| 2 | +<html lang="en"> | |
| 3 | +<head> | |
| 4 | + <meta charset="UTF-8"> | |
| 5 | + <meta name="Generator" content="EditPlus®"> | |
| 6 | + <meta name="Author" content=""> | |
| 7 | + <meta name="Keywords" content=""> | |
| 8 | + <meta name="Description" content=""> | |
| 9 | + <title>Document</title> | |
| 10 | +</head> | |
| 11 | +<body> | |
| 12 | +<audio width="500" height="300" controls autoplay preload="auto" src="data:audio/wav;base64,UklGRqQCAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YYACAAC2+oj6Dfly+hP8i/pY+pv7dfpq+Uj5Ift1/L37pfo++7T6hvtI+T76s/vn+jj5Mfvt+ir70vuh+Vf5M/t7+nT8IPv1+JX7hvqQ+W/6K/pf+yf79PrG+pz6wvqJ+Qf6Evur+of7+PpC+ln6RPpX+mj6mPpP+hb7Ufza+TT6hvoR+e36Nfr9+ZT80Po1+Wr8R/rk+dX4FPuJ/DX7Afr6+y77iPiX+Y36bPug+tT7nPud+rb5jPn++dz5tfv5+8X6bfvU+qb6fPoj+Qr6gfxy+9f5Ifr9+8n6YPif+hT8WPyy+cH6t/tC+nb5ofvC+vb5pfuN+sD6YfyI+ev5+voE+qT8lfuf+n77Kvpy+Wv7n/rn+f/6ZPwK+rj5Lfth+i35Rfre+gz7Ovr5+qb7DPoz9+v5ZPwl+gT7SPsL+9P6Ovpo+jr7L/oh+z38//mt+U38ifo3+u35qfnL/IP7Wfr/+fX6P/tj+S/4ePvR/a77vfnM+sL7TfoJ+j37lfrI+q/73foe+rf50/oU+k37e/o6+436bvrD+hH7rvnh+Wv6kfsD/IX6uPqK+rj5d/ok+wj6Rvyr+or7zvsf+lf6vvlI+hf8aPrA+SX7U/uB+sL5b/rK++P6Zfok+736nvpM/CH6rPiI+kD7WPy/+zX7uvnt+dT6pvto+V76aPyM+k/6h/q6+uj6wvnN+tb8zPp4+aP7xPqA+kP6C/pw+/r7f/rm+Sn7A/op+kv66Pog+j/75Pw8/D/50vj8+Qv7ufpE+aj7Q/05++X5qPlQ+hv8+fgc+0b8GPlg+sP6tPmq+mD6lPlD++v7uvmZ+t36Jfpd+l75FPzq+pD6hvs8+/j6QPq4+E/7data:audio/wav;base64,UklGRqQCAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YYACAACp+w76g/tP/KD6aPpp+VD6zvoP+hj8Oftd+ZH6qft4+Vf6m/pT+9v8RPrq+eD6Afq9+XX6rfp4/Mn6kfrE+iP5jPuW+iH5dfot+0X8ePzC+Zj4Eftj+1n5nflV+k78gvvT+Vv7kPlc+KX7Lfua+8T8S/qd+pP45/mW+376S/oB/RD7tvoI+yn6Xfml+A77BPy6+2b6Ffw8+Z/5+fkD+Tj8pfx7+7f5Cfro+hz6bfhG+3D8YfvG+Xz5SPp8+9T6b/my+oH8vvzl+YL5Rvv0+hX64fo7+Gn7sfzA+hr7bPvM+Nv5Lfp3+sv7jvvm+n/7PPq6+q/5dvhF+nD8JvzS+or7Uvu7+H/60fqw+2z7L/tn+8760fid+WD56Pob++36a/us+nP58fky+Tv7m/hf+p78lPpA+XT6zPkx+5D5yPnF/Fj8oPlG+eH6K/vX+Zr5c/wQ/AH7C/rq+h76Uvs6+m/4mvoP/FP8pPr8+WH7Hvr4+Db7LPxN+4H6tfst+pT51/qp+2v5YfoB/af8sfun+WP5EvuK+Vf5VPuY+9X7nfs4+mb6QPn/+Qj8vvtq+i36tfu2+oj6Cvow+pf68vtR+jn5avu0++j6MPr4+ZH6G/uZ+0D6yvpM+kH5Svtr+r/7/Pt0+g373/ph+tP6yvip+ZX8Mvwj+y36I/j/+a77Jvol+6/7gfyP+kv6k/lb+Vj8EPvm+fX6kPzw+f/6Cfq/+QP6N/uP+vT7DfuP+rX6Tvqx+V/7ufh9+hj8Dvra+p369fmM/Mj6GvvQ+gT6x/lP+7b65Ppm+qf5a/su+xb64/lt+uj7g/qc+XL5F/tP++j76/kv+lr8e/uf+WL5O/zY+xT6data:audio/wav;base64,UklGRqQCAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YYACAADC+cz7APvM+XT6D/lp+7v73Pqo+3T6XPkn++r6Qvrb+gn7L/wk+xv5+vk++nL7qvsT+fb8ev0x+g74OPmx+xb69frB+3D9J/q/+OL6RfuB+dP5Hfpx+zT7/Ppj+u36G/om++35a/r5+WD6+vtS+x/7lfoe+OL5NPo+/Or6Mvpq+s/7dfl/+LT7Ifww+or63Pom+9L5GvmD+4361/qj++v6k/su+kf5avsg+0T56vvb+uX5L/r7+kP6W/v2+Tn7tPyD+qT5YPkP+7f77Pkp+kH7DvuE+q76ufvb+wL6JvjD+z/7x/o0+9H6K/uQ+Ub5EvpG+w77p/uq+e75Gfyk+tj5h/tP+xz77voU/CL6VvkZ+YL7MPt6+474f/pD/AT6j/jj+Rf7v/uO+UT5uPxf+jz4u/tD+/v5mPlc+1L83fqJ+Tj7cPvX+jb5L/uD/Eb8/fhl+q37g/q/+KP7efrT+iX7BPzA+xH6+fjE+of6L/vK+bH6LPzH+ib5j/uZ+k/6k/pL+/P7KPrr+QP7nvko+k77Q/qW+W/7G/pj+Qv6cvm1+tv7Nvq++yX79/p5+iD5B/qC+0/7xfqX+6X5cfo0+mz6n/r++Gf7FfvL+pf7Y/q7+ez7TPnF+xf8DfrZ+pz69Pm/+4v6A/kA/G38fPpt+Qj7vvqK+9v5E/p4+6b7JPzm+fD4Zfox+/T6nPsD+zH7W/uc+gP7J/pD+sr70fmd+tr60/x/+9D5KPkl/AL6n/lj+7X7lPww+jr5r/rj+Zv6BP3F+g/7y/oI+2D6+/ic+mT6/foW+pH7LPpa+tj6svpL+mr6+fpH+0P6ZfoC+636wvme+pz5YPsY/B/66/qj+xv6"></audio> | |
| 13 | +</body> | |
| 14 | +</html> | ... | ... |
src/main/resources/video.html
0 → 100644
| 1 | +++ a/src/main/resources/video.html | |
| 1 | +<html> | |
| 2 | +<head> | |
| 3 | + <title>HTTP-Flv Test</title> | |
| 4 | +</head> | |
| 5 | +<script type="text/javascript" src="//cdn.bootcss.com/flv.js/1.5.0/flv.min.js"></script> | |
| 6 | +<body> | |
| 7 | +<video id="xxoo" autoplay></video> | |
| 8 | +<script type="text/javascript"> | |
| 9 | + function play() | |
| 10 | + { | |
| 11 | + var el = document.getElementById('xxoo'); | |
| 12 | + | |
| 13 | + var player = flvjs.createPlayer({ | |
| 14 | + type : 'flv', | |
| 15 | + url : '/video/' + location.hash.substring(1), | |
| 16 | + isLive : true, | |
| 17 | + enableStashBuffer : false, | |
| 18 | + enableWorker : true, | |
| 19 | + stashInitialSize : 128 | |
| 20 | + }); | |
| 21 | + player.on('media_info', function() | |
| 22 | + { | |
| 23 | + console.log('media_info'); | |
| 24 | + console.log(player.mediaInfo); | |
| 25 | + player.play(); | |
| 26 | + }); | |
| 27 | + player.attachMediaElement(el); | |
| 28 | + player.load(); | |
| 29 | + } | |
| 30 | +</script> | |
| 31 | +<button onclick="play()">Play</button> | |
| 32 | +</body> | |
| 33 | +</html> | |
| 0 | 34 | \ No newline at end of file | ... | ... |