├── Android ├── AndroidManifest.xml ├── ant.properties ├── assets │ ├── hook.js │ ├── index.html │ └── zepto.min.js ├── bin │ └── m3u8player-debug.apk ├── build.xml ├── html │ ├── index.html │ └── play.html ├── libs │ └── armeabi-v7a │ │ └── libppeasy.so ├── local.properties ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-ldpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── layout │ │ └── main.xml │ └── values │ │ └── strings.xml └── src │ └── com │ └── ppeasy │ └── m3u8player │ ├── VideoViewEx.java │ └── m3u8player.java ├── HLS.js ├── hls.min.js └── index.html ├── README.md ├── flashls-dev ├── .actionScriptProperties ├── .editorconfig ├── .flexLibProperties ├── .gitignore ├── .project ├── API.md ├── LICENSE ├── README.md ├── bin │ ├── debug │ │ ├── flashls.swc │ │ ├── flashlsChromeless.swf │ │ ├── flashlsFlowPlayer.swf │ │ ├── flashlsOSMF.swc │ │ └── flashlsOSMF.swf │ └── release │ │ ├── flashls.swc │ │ ├── flashlsChromeless.swf │ │ ├── flashlsFlowPlayer.swf │ │ ├── flashlsOSMF.swc │ │ └── flashlsOSMF.swf ├── build │ ├── add-opt-in.py │ ├── build.bat │ ├── build.sh │ └── build_chromeless.sh ├── docs │ └── 10.1.1.300.5957.pdf ├── examples │ ├── chromeless │ │ ├── flashlsAPI.js │ │ ├── index.html │ │ ├── jQuery.min.js │ │ └── metrics.html │ ├── flowplayer │ │ ├── flowplayer-3.2.12.min.js │ │ ├── flowplayer.controls.swf │ │ ├── flowplayer.ipad-3.2.12.min.js │ │ ├── flowplayer.swf │ │ ├── index.html │ │ └── jQuery.min.js │ ├── libs │ │ ├── JSLoaderFragment.js │ │ ├── JSLoaderPlaylist.js │ │ ├── ParsedQueryString.js │ │ ├── canvas.js │ │ ├── js2flash.js │ │ ├── jsonpack.js │ │ ├── metrics.js │ │ └── swfobject.js │ └── osmf │ │ ├── GrindPlayer.html │ │ ├── GrindPlayer.swf │ │ ├── StrobeMediaPlayback.html │ │ ├── StrobeMediaPlayback.swf │ │ └── images │ │ ├── adobe-lq.png │ │ ├── osmf_horizontal_red.png │ │ └── poster.png ├── lib │ ├── blooddy_crypto.swc │ ├── flowplayer │ │ ├── flowplayer-classes.xml │ │ └── flowplayer.swc │ └── osmf │ │ ├── OSMF.swc │ │ └── exclude-sources.xml └── src │ └── org │ └── mangui │ ├── basic │ └── Player.as │ ├── chromeless │ ├── ChromelessPlayer.as │ └── StatsHandler.as │ ├── flowplayer │ ├── HLSPluginFactory.as │ └── HLSStreamProvider.as │ ├── hls │ ├── HLS.as │ ├── HLSSettings.as │ ├── constant │ │ ├── HLSLoaderTypes.as │ │ ├── HLSMaxLevelCappingMode.as │ │ ├── HLSPlayStates.as │ │ ├── HLSSeekMode.as │ │ ├── HLSSeekStates.as │ │ └── HLSTypes.as │ ├── controller │ │ ├── AudioTrackController.as │ │ ├── BufferThresholdController.as │ │ ├── FPSController.as │ │ └── LevelController.as │ ├── demux │ │ ├── AACDemuxer.as │ │ ├── AVCC.as │ │ ├── AudioFrame.as │ │ ├── DemuxHelper.as │ │ ├── Demuxer.as │ │ ├── ExpGolomb.as │ │ ├── ID3.as │ │ ├── ID3Tag.as │ │ ├── MP3Demuxer.as │ │ ├── Nalu.as │ │ ├── PES.as │ │ ├── SPSInfo.as │ │ ├── TSDemuxer.as │ │ └── VideoFrame.as │ ├── event │ │ ├── HLSError.as │ │ ├── HLSEvent.as │ │ ├── HLSLoadMetrics.as │ │ ├── HLSMediatime.as │ │ └── HLSPlayMetrics.as │ ├── flv │ │ └── FLVTag.as │ ├── loader │ │ ├── AltAudioFragmentLoader.as │ │ ├── AltAudioLevelLoader.as │ │ ├── FragmentLoader.as │ │ └── LevelLoader.as │ ├── model │ │ ├── AudioTrack.as │ │ ├── Fragment.as │ │ ├── FragmentData.as │ │ └── Level.as │ ├── playlist │ │ ├── AltAudioTrack.as │ │ ├── DataUri.as │ │ └── Manifest.as │ ├── stream │ │ ├── HLSNetStream.as │ │ ├── HLSNetStreamClient.as │ │ └── StreamBuffer.as │ └── utils │ │ ├── AES.as │ │ ├── DateUtil.as │ │ ├── FastAESKey.as │ │ ├── Hex.as │ │ ├── JSURLLoader.as │ │ ├── JSURLStream.as │ │ ├── Log.as │ │ ├── PTS.as │ │ ├── Params2Settings.as │ │ ├── ScaleVideo.as │ │ └── StringUtil.as │ └── osmf │ └── plugins │ ├── HLSDynamicPlugin.as │ ├── HLSMediaElement.as │ ├── HLSPlugin.as │ ├── loader │ ├── HLSLoadFromDocumentElement.as │ ├── HLSLoaderBase.as │ └── HLSNetLoader.as │ ├── traits │ ├── HLSAlternativeAudioTrait.as │ ├── HLSBufferTrait.as │ ├── HLSClosedCaptionsState.as │ ├── HLSClosedCaptionsTrait.as │ ├── HLSDisplayObjectTrait.as │ ├── HLSDynamicStreamTrait.as │ ├── HLSMediaTraitType.as │ ├── HLSNetStreamLoadTrait.as │ ├── HLSPlayTrait.as │ ├── HLSSeekTrait.as │ └── HLSTimeTrait.as │ └── utils │ └── ErrorManager.as ├── index.html ├── ios-plat ├── m3u8player.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── dzy.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── dzy.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── m3u8player.xcscheme │ │ └── xcschememanagement.plist ├── m3u8player │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ ├── index.html │ ├── libppeasy.a │ ├── main.mm │ ├── msui │ │ ├── css │ │ │ ├── sm-extend.css │ │ │ ├── sm-extend.min.css │ │ │ ├── sm.css │ │ │ └── sm.min.css │ │ └── js │ │ │ ├── sm-city-picker.js │ │ │ ├── sm-city-picker.min.js │ │ │ ├── sm-extend.js │ │ │ ├── sm-extend.min.js │ │ │ ├── sm.js │ │ │ └── sm.min.js │ └── zepto.min.js ├── m3u8playerTests │ ├── Info.plist │ └── m3u8playerTests.m └── m3u8playerUITests │ ├── Info.plist │ └── m3u8playerUITests.m └── nginx-rtmp ├── FAQ nginx-win version.txt ├── Readme nginx-win version.txt ├── Tweak-Optimize tcpip parameters for nginx connections.reg ├── conf ├── EBLB │ ├── iworkcomproto.lua │ ├── upstream_EBLB_with_IWCP.txt │ ├── upstream_candc.conf │ ├── upstreamcontrol.lua │ └── upstreamstatus.lua ├── fastcgi.conf ├── fastcgi_params ├── koi-utf ├── koi-win ├── mime.types ├── mysite.rules ├── naxsi_core.rules ├── nginx-org.conf ├── nginx-simple-WAF.conf ├── nginx-win.conf ├── nginx.conf ├── php-opcache-example.ini ├── php-xcache-example.ini ├── scgi_params ├── uwsgi_params ├── vhts │ ├── VHTS.txt │ ├── vtsvalues-eop.js │ └── vtsvalues.js └── win-utf ├── contrib ├── README ├── geo2nginx.pl ├── unicode2nginx │ ├── koi-utf │ ├── unicode-to-nginx.pl │ └── win-utf └── vim │ ├── ftdetect │ └── nginx.vim │ ├── indent │ └── nginx.vim │ └── syntax │ └── nginx.vim ├── docs ├── LICENSE ├── OpenSSL.LICENSE ├── PCRE.LICENCE ├── README └── zlib.LICENSE ├── html ├── 50x.html └── index.html ├── logs ├── access.log ├── error.log └── nginx.pid ├── lua51.dll ├── nginx-rtmp-module └── stat.xsl ├── nginx.exe ├── nginx_basic.exe └── tmp └── app ├── test-0.ts ├── test-1.ts ├── test-10.ts ├── test-11.ts ├── test-12.ts ├── test-2.ts ├── test-3.ts ├── test-4.ts ├── test-5.ts ├── test-6.ts ├── test-7.ts ├── test-8.ts ├── test-9.ts └── test.m3u8 /Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Android/ant.properties: -------------------------------------------------------------------------------- 1 | # This file is used to override default values used by the Ant build system. 2 | # 3 | # This file must be checked into Version Control Systems, as it is 4 | # integral to the build system of your project. 5 | 6 | # This file is only used by the Ant script. 7 | 8 | # You can use this to override default values such as 9 | # 'source.dir' for the location of your java source folder and 10 | # 'out.dir' for the location of your output folder. 11 | 12 | # You can also use it define how the release builds are signed by declaring 13 | # the following properties: 14 | # 'key.store' for the location of your keystore and 15 | # 'key.alias' for the name of the key to use. 16 | # The password will be asked during the build when you use the 'release' target. 17 | 18 | -------------------------------------------------------------------------------- /Android/assets/hook.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | fetch('http://127.0.0.1:1960/Close?').then(function(res){ 4 | if (res.ok) { 5 | var inth=null; 6 | inth=setInterval(function (){ 7 | var addf=0; 8 | for(var k=0;k 2 | 3 | 4 | 5 | 17 | 20 | 21 | 34 | 35 |
36 |

输入域名

37 |

38 | 39 |

M3U8Player

40 |

41 |

42 | 44 |

45 |

46 |
47 | 48 |
49 |
50 | 51 | -------------------------------------------------------------------------------- /Android/bin/m3u8player-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/Android/bin/m3u8player-debug.apk -------------------------------------------------------------------------------- /Android/html/play.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 123 5 | 8 | 9 | -------------------------------------------------------------------------------- /Android/libs/armeabi-v7a/libppeasy.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/Android/libs/armeabi-v7a/libppeasy.so -------------------------------------------------------------------------------- /Android/local.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | 7 | # location of the SDK. This is only used by Ant 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | sdk.dir=F:\\android-sdk-windows 11 | -------------------------------------------------------------------------------- /Android/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /Android/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-23 15 | -------------------------------------------------------------------------------- /Android/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/Android/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Android/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/Android/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /Android/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/Android/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Android/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/Android/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Android/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Android/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | m3u8player 4 | MainActivity 5 | 6 | -------------------------------------------------------------------------------- /Android/src/com/ppeasy/m3u8player/VideoViewEx.java: -------------------------------------------------------------------------------- 1 | package com.ppeasy.m3u8player; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.VideoView; 6 | 7 | /** 8 | * 自动全屏的VideoView 9 | */ 10 | public class VideoViewEx extends VideoView { 11 | 12 | private int videoWidth; 13 | private int videoHeight; 14 | 15 | public VideoViewEx(Context context) { 16 | super(context); 17 | } 18 | 19 | public VideoViewEx(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | } 22 | 23 | public VideoViewEx(Context context, AttributeSet attrs, int defStyle) { 24 | super(context, attrs, defStyle); 25 | } 26 | 27 | @Override 28 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 29 | int width = getDefaultSize(videoWidth, widthMeasureSpec); 30 | int height = getDefaultSize(videoHeight, heightMeasureSpec); 31 | if (videoWidth > 0 && videoHeight > 0) { 32 | if (videoWidth * height > width * videoHeight) { 33 | height = width * videoHeight / videoWidth; 34 | } else if (videoWidth * height < width * videoHeight) { 35 | width = height * videoWidth / videoHeight; 36 | } 37 | } 38 | setMeasuredDimension(width, height); 39 | } 40 | 41 | public int getVideoWidth() { 42 | return videoWidth; 43 | } 44 | 45 | public void setVideoWidth(int videoWidth) { 46 | this.videoWidth = videoWidth; 47 | } 48 | 49 | public int getVideoHeight() { 50 | return videoHeight; 51 | } 52 | 53 | public void setVideoHeight(int videoHeight) { 54 | this.videoHeight = videoHeight; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /HLS.js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | hls.js 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | m3u8player提供了网页和app播放方式播放m3u8直播源和点播链接,全面支持Windows、Android、IOS平台。 2 | 3 | P2P版本的M3u8播放器项目: https://github.com/SeaHaige/pkplayer 4 | 5 | HLS.js是网页HTML5版的m3u8播放器,支持chrome、FIREFOX等浏览器。 6 | 7 | Demo : https://seahaige.github.io/m3u8player/HLS.js/index.html 8 | 9 | flashls-dev是flash版的m3u8播放器,可在IE、Chrome下运行。 10 | 11 | Demo : https://seahaige.github.io/m3u8player/flashls-dev/examples/flowplayer 12 | 13 | nginx-rtmp是HLS服务器,在windows下运行。 14 | 15 | OBS的推流路径:rtmp://127.0.0.1/hls/test 16 | 17 | M3U8播放地址:http://127.0.0.1/hls/test.m3u8 18 | 19 | m3u8player也可以支持P2P播放模式,使用ppeasy(P2P传输SDK),其特点是无需架设穿透服务器,用户之间直接进行数据的交换,从而降低服务器带宽需求。 20 | 21 | QQ技术交流群: 466907566 22 | -------------------------------------------------------------------------------- /flashls-dev/.actionScriptProperties: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /flashls-dev/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /flashls-dev/.flexLibProperties: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /flashls-dev/.gitignore: -------------------------------------------------------------------------------- 1 | *.swf.cache 2 | *.swc.cache 3 | .metadata 4 | .settings 5 | /streams.js 6 | ======= 7 | 8 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 9 | 10 | *.iml 11 | 12 | ## Directory-based project format: 13 | .idea/ 14 | # if you remove the above rule, at least ignore the following: 15 | 16 | # User-specific stuff: 17 | # .idea/workspace.xml 18 | # .idea/tasks.xml 19 | # .idea/dictionaries 20 | 21 | # Sensitive or high-churn files: 22 | # .idea/dataSources.ids 23 | # .idea/dataSources.xml 24 | # .idea/sqlDataSources.xml 25 | # .idea/dynamic.xml 26 | # .idea/uiDesigner.xml 27 | 28 | # Gradle: 29 | # .idea/gradle.xml 30 | # .idea/libraries 31 | 32 | # Mongo Explorer plugin: 33 | # .idea/mongoSettings.xml 34 | 35 | ## File-based project format: 36 | *.ipr 37 | *.iws 38 | 39 | ## Plugin-specific files: 40 | 41 | # IntelliJ 42 | /out/ 43 | 44 | # mpeltonen/sbt-idea plugin 45 | .idea_modules/ 46 | 47 | # JIRA plugin 48 | atlassian-ide-plugin.xml 49 | 50 | # Crashlytics plugin (for Android Studio and IntelliJ) 51 | com_crashlytics_export_strings.xml 52 | crashlytics.properties 53 | crashlytics-build.properties 54 | 55 | # Flash Builder 56 | /bin/flashls.swc 57 | /bin-temp 58 | -------------------------------------------------------------------------------- /flashls-dev/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | flashls 4 | 5 | 6 | 7 | 8 | 9 | com.adobe.flexbuilder.project.flexbuilder 10 | 11 | 12 | 13 | 14 | com.powerflasher.fdt.core.FlashBuilder 15 | 16 | 17 | 18 | 19 | 20 | com.adobe.flexbuilder.project.flexlibnature 21 | com.adobe.flexbuilder.project.actionscriptnature 22 | com.powerflasher.fdt.core.FlashNature 23 | 24 | 25 | -------------------------------------------------------------------------------- /flashls-dev/bin/debug/flashls.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/debug/flashls.swc -------------------------------------------------------------------------------- /flashls-dev/bin/debug/flashlsChromeless.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/debug/flashlsChromeless.swf -------------------------------------------------------------------------------- /flashls-dev/bin/debug/flashlsFlowPlayer.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/debug/flashlsFlowPlayer.swf -------------------------------------------------------------------------------- /flashls-dev/bin/debug/flashlsOSMF.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/debug/flashlsOSMF.swc -------------------------------------------------------------------------------- /flashls-dev/bin/debug/flashlsOSMF.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/debug/flashlsOSMF.swf -------------------------------------------------------------------------------- /flashls-dev/bin/release/flashls.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/release/flashls.swc -------------------------------------------------------------------------------- /flashls-dev/bin/release/flashlsChromeless.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/release/flashlsChromeless.swf -------------------------------------------------------------------------------- /flashls-dev/bin/release/flashlsFlowPlayer.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/release/flashlsFlowPlayer.swf -------------------------------------------------------------------------------- /flashls-dev/bin/release/flashlsOSMF.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/release/flashlsOSMF.swc -------------------------------------------------------------------------------- /flashls-dev/bin/release/flashlsOSMF.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/bin/release/flashlsOSMF.swf -------------------------------------------------------------------------------- /flashls-dev/build/build_chromeless.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -z "$FLEXPATH" ]; then 3 | echo "Usage FLEXPATH=/path/to/flex/sdk sh ./build.sh" 4 | exit 5 | fi 6 | 7 | OPT_DEBUG="-use-network=false \ 8 | -optimize=true \ 9 | -debug=true \ 10 | -library-path+=../lib/blooddy_crypto.swc \ 11 | -define=CONFIG::LOGGING,true \ 12 | -define=CONFIG::FLASH_11_1,true" 13 | 14 | OPT_RELEASE="-use-network=false \ 15 | -optimize=true \ 16 | -debug=false \ 17 | -library-path+=../lib/blooddy_crypto.swc \ 18 | -define=CONFIG::LOGGING,false \ 19 | -define=CONFIG::FLASH_11_1,true" 20 | 21 | echo "Compiling bin/release/flashlsChromeless.swf" 22 | $FLEXPATH/bin/mxmlc ../src/org/mangui/chromeless/ChromelessPlayer.as \ 23 | -source-path ../src \ 24 | -o ../bin/release/flashlsChromeless.swf \ 25 | $OPT_RELEASE \ 26 | -target-player="11.1" \ 27 | -default-size 480 270 \ 28 | -default-background-color=0x000000 29 | ./add-opt-in.py ../bin/release/flashlsChromeless.swf 30 | 31 | echo "Compiling bin/debug/flashlsChromeless.swf" 32 | $FLEXPATH/bin/mxmlc ../src/org/mangui/chromeless/ChromelessPlayer.as \ 33 | -source-path ../src \ 34 | -o ../bin/debug/flashlsChromeless.swf \ 35 | $OPT_DEBUG \ 36 | -target-player="11.1" \ 37 | -default-size 480 270 \ 38 | -default-background-color=0x000000 39 | ./add-opt-in.py ../bin/debug/flashlsChromeless.swf 40 | -------------------------------------------------------------------------------- /flashls-dev/docs/10.1.1.300.5957.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/docs/10.1.1.300.5957.pdf -------------------------------------------------------------------------------- /flashls-dev/examples/flowplayer/flowplayer.controls.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/examples/flowplayer/flowplayer.controls.swf -------------------------------------------------------------------------------- /flashls-dev/examples/flowplayer/flowplayer.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/examples/flowplayer/flowplayer.swf -------------------------------------------------------------------------------- /flashls-dev/examples/flowplayer/index.html: -------------------------------------------------------------------------------- 1 | 2 | Flowplayer - flashls 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 29 |

flashls 30 | within Flowplayer 31 |

32 |
33 | 34 | 35 |
73 |

74 | This demonstrates a setup to play a VOD HLS stream within Flowplayer 75 | with a fallback to Html5 for Ipad. 76 |

77 | Examples 78 | 79 |

Basic example with a single bitrate

80 |
81 |

flowplayer("player", "flowplayer.swf", {
// configure the required plugins
plugins: {
httpstreaming: {
url: 'flashlsFlowPlayer.swf'
}
},
clip: {
url: "http://184.72.239.149/vod/smil:bigbuckbunnyiphone.smil/chunklist-b400000.m3u8",
ipadUrl: "http://184.72.239.149/vod/smil:bigbuckbunnyiphone.smil/chunklist-b400000.m3u8",
urlResolvers: ["httpstreaming","brselect"],
provider: "httpstreaming",
autoPlay: false
},
log: {
level: 'debug',
filter: 'org.osmf.*, org.electroteque.m3u8.*, org.flowplayer.bitrateselect.*'
}
}).ipad();
82 |
83 |
84 |
85 | 86 | -------------------------------------------------------------------------------- /flashls-dev/examples/libs/JSLoaderFragment.js: -------------------------------------------------------------------------------- 1 | var JSLoaderFragment = { 2 | 3 | requestFragment : function(instanceId,url, resourceLoadedFlashCallback, resourceFailureFlashCallback) { 4 | //console.log("JSURLStream.onRequestResource"); 5 | if(!this.flashObject) { 6 | this.flashObject = getFlashMovieObject(instanceId); 7 | } 8 | this.xhrGET(url,this.xhrReadBytes, this.xhrTransferFailed, resourceLoadedFlashCallback, resourceFailureFlashCallback, "arraybuffer"); 9 | }, 10 | abortFragment : function(instanceId) { 11 | if(this.xhr &&this.xhr.readyState !== 4) { 12 | console.log("JSLoaderFragment:abort XHR"); 13 | this.xhr.abort(); 14 | } 15 | }, 16 | xhrGET : function (url,loadcallback, errorcallback,resourceLoadedFlashCallback, resourceFailureFlashCallback, responseType) { 17 | var xhr = new XMLHttpRequest(); 18 | this.xhr = xhr; 19 | xhr.binding = this; 20 | xhr.resourceLoadedFlashCallback = resourceLoadedFlashCallback; 21 | xhr.resourceFailureFlashCallback = resourceFailureFlashCallback; 22 | xhr.open("GET", url, loadcallback? true: false); 23 | if (responseType) { 24 | xhr.responseType = responseType; 25 | } 26 | if (loadcallback) { 27 | xhr.onload = loadcallback; 28 | xhr.onerror= errorcallback; 29 | xhr.send(); 30 | } else { 31 | xhr.send(); 32 | return xhr.status == 200? xhr.response: ""; 33 | } 34 | }, 35 | xhrReadBytes : function(event) { 36 | //console.log("fragment loaded"); 37 | var len = event.currentTarget.response.byteLength; 38 | var t0 = new Date(); 39 | var res = base64ArrayBuffer(event.currentTarget.response); 40 | var t1 = new Date(); 41 | this.binding.flashObject[this.resourceLoadedFlashCallback](res,len); 42 | var t2 = new Date(); 43 | console.log('encoding/toFlash:' + (t1-t0) + '/' + (t2-t1)); 44 | console.log('encoding speed/toFlash:' + Math.round(len/(t1-t0)) + 'kB/s/' + Math.round(res.length/(t2-t1)) + 'kB/s'); 45 | }, 46 | xhrTransferFailed : function(oEvent) { 47 | console.log("An error occurred while transferring the file :" + oEvent.target.status); 48 | this.binding.flashObject[this.resourceFailureFlashCallback](res); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /flashls-dev/examples/libs/JSLoaderPlaylist.js: -------------------------------------------------------------------------------- 1 | var JSLoaderPlaylist = { 2 | 3 | requestPlaylist : function(instanceId,url, resourceLoadedFlashCallback, resourceFailureFlashCallback) { 4 | //console.log("JSURLLoader.onRequestResource"); 5 | if(!this.flashObject) { 6 | this.flashObject = getFlashMovieObject(instanceId); 7 | } 8 | this.xhrGET(url,this.xhrReadBytes, this.xhrTransferFailed, resourceLoadedFlashCallback, resourceFailureFlashCallback); 9 | }, 10 | abortPlaylist : function(instanceId) { 11 | if(this.xhr &&this.xhr.readyState !== 4) { 12 | console.log("JSLoaderPlaylist:abort XHR"); 13 | this.xhr.abort(); 14 | } 15 | }, 16 | xhrGET : function (url,loadcallback, errorcallback,resourceLoadedFlashCallback, resourceFailureFlashCallback) { 17 | var xhr = new XMLHttpRequest(); 18 | xhr.binding = this; 19 | this.xhr = xhr; 20 | xhr.resourceLoadedFlashCallback = resourceLoadedFlashCallback; 21 | xhr.resourceFailureFlashCallback = resourceFailureFlashCallback; 22 | xhr.open("GET", url, loadcallback? true: false); 23 | if (loadcallback) { 24 | xhr.onload = loadcallback; 25 | xhr.onerror= errorcallback; 26 | xhr.send(); 27 | } else { 28 | xhr.send(); 29 | return xhr.status == 200? xhr.response: ""; 30 | } 31 | }, 32 | xhrReadBytes : function(event) { 33 | //console.log("playlist loaded"); 34 | this.binding.flashObject[this.resourceLoadedFlashCallback](event.currentTarget.responseText); 35 | }, 36 | xhrTransferFailed : function(oEvent) { 37 | console.log("An error occurred while transferring the file :" + oEvent.target.status); 38 | this.binding.flashObject[this.resourceFailureFlashCallback](res); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /flashls-dev/examples/libs/ParsedQueryString.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * 3 | * ParsedQueryString version 1.0 4 | * Copyright 2007, Jeff Mott . All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms with or without 7 | * modification are permitted provided that the above copyright notice, 8 | * this condition, and the following disclaimer are retained. 9 | * 10 | * THIS SOFTWARE IS PROVIDED AS IS, AND ANY EXPRESS OR IMPLIED WARRANTIES, 11 | * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 12 | * FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE 13 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 14 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT 15 | * LIMITED TO PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 16 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 17 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 18 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 19 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | * 21 | ******************************************************************************/ 22 | 23 | function ParsedQueryString() { 24 | this._init(); 25 | } 26 | 27 | ParsedQueryString.version = '1.0'; 28 | 29 | ParsedQueryString.prototype = 30 | { 31 | _init: 32 | function () 33 | { 34 | this._parameters = {}; 35 | 36 | if (location.search.length <= 1) 37 | return; 38 | var pairs = location.search.substr(1).split(/[&;]/); 39 | for (var i = 0; i < pairs.length; i++) 40 | { 41 | var pair = pairs[i].split(/=/); 42 | var name = this._decodeURL(pair[0]); 43 | if (Boolean(pair[1])) 44 | { 45 | var value = this._decodeURL(pair[1]); 46 | if (Boolean(this._parameters[name])) 47 | this._parameters[name].push(value); 48 | else 49 | this._parameters[name] = [value]; 50 | } 51 | } 52 | }, 53 | 54 | _decodeURL: 55 | function (url) { 56 | return decodeURIComponent(url.replace(/\+/g, " ")); 57 | }, 58 | 59 | param: 60 | function (name) 61 | { 62 | if (Boolean(this._parameters[name])) 63 | return this._parameters[name][0]; 64 | else 65 | return ""; 66 | }, 67 | 68 | params: 69 | function (name) 70 | { 71 | if (Boolean(name)) 72 | { 73 | if (Boolean(this._parameters[name])) 74 | { 75 | var values = []; 76 | for (var i = 0; i < this._parameters[name].length; i++) 77 | values.push(this._parameters[name][i]); 78 | return values; 79 | } 80 | else 81 | return []; 82 | } 83 | else 84 | { 85 | var names = []; 86 | for (var name in this._parameters) 87 | names.push(name); 88 | return names; 89 | } 90 | } 91 | }; 92 | -------------------------------------------------------------------------------- /flashls-dev/examples/libs/js2flash.js: -------------------------------------------------------------------------------- 1 | function getFlashMovieObject(movieName) 2 | { 3 | if (window.document[movieName]) 4 | { 5 | return window.document[movieName]; 6 | } 7 | if (navigator.appName.indexOf("Microsoft Internet")==-1) 8 | { 9 | if (document.embeds && document.embeds[movieName]) 10 | return document.embeds[movieName]; 11 | } 12 | else // if (navigator.appName.indexOf("Microsoft Internet")!=-1) 13 | { 14 | return document.getElementById(movieName); 15 | } 16 | } 17 | 18 | function base64ArrayBuffer(arrayBuffer) { 19 | var bytes = new Uint8Array(arrayBuffer),byteLength = bytes.byteLength; 20 | if(window.btoa) { 21 | var binary = ''; 22 | for (var i = 0; i < byteLength; i++) { 23 | binary += String.fromCharCode(bytes[i]); 24 | } 25 | return window.btoa(binary); 26 | } else { 27 | var base64 = '' 28 | var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' 29 | var byteRemainder = byteLength % 3 30 | var mainLength = byteLength - byteRemainder 31 | var a, b, c, d, chunk 32 | 33 | for (var i = 0; i < mainLength; i = i + 3) { 34 | chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2] 35 | a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18 36 | b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12 37 | c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6 38 | d = chunk & 63 // 63 = 2^6 - 1 39 | base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d] 40 | } 41 | 42 | if (byteRemainder == 1) { 43 | chunk = bytes[mainLength] 44 | a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2 45 | b = (chunk & 3) << 4 // 3 = 2^2 - 1 46 | base64 += encodings[a] + encodings[b] + '==' 47 | } else if (byteRemainder == 2) { 48 | chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1] 49 | a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10 50 | b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4 51 | c = (chunk & 15) << 2 // 15 = 2^4 - 1 52 | base64 += encodings[a] + encodings[b] + encodings[c] + '=' 53 | } 54 | return base64; 55 | } 56 | } -------------------------------------------------------------------------------- /flashls-dev/examples/osmf/GrindPlayer.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/examples/osmf/GrindPlayer.swf -------------------------------------------------------------------------------- /flashls-dev/examples/osmf/StrobeMediaPlayback.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/examples/osmf/StrobeMediaPlayback.swf -------------------------------------------------------------------------------- /flashls-dev/examples/osmf/images/adobe-lq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/examples/osmf/images/adobe-lq.png -------------------------------------------------------------------------------- /flashls-dev/examples/osmf/images/osmf_horizontal_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/examples/osmf/images/osmf_horizontal_red.png -------------------------------------------------------------------------------- /flashls-dev/examples/osmf/images/poster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/examples/osmf/images/poster.png -------------------------------------------------------------------------------- /flashls-dev/lib/blooddy_crypto.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/lib/blooddy_crypto.swc -------------------------------------------------------------------------------- /flashls-dev/lib/flowplayer/flowplayer.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/lib/flowplayer/flowplayer.swc -------------------------------------------------------------------------------- /flashls-dev/lib/osmf/OSMF.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/flashls-dev/lib/osmf/OSMF.swc -------------------------------------------------------------------------------- /flashls-dev/lib/osmf/exclude-sources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/basic/Player.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.basic { 5 | import org.mangui.hls.HLS; 6 | import org.mangui.hls.event.HLSEvent; 7 | 8 | import flash.display.Sprite; 9 | import flash.media.Video; 10 | 11 | public class Player extends Sprite { 12 | private var hls : HLS = null; 13 | private var video : Video = null; 14 | 15 | public function Player() { 16 | hls = new HLS(); 17 | hls.stage = this.stage; 18 | video = new Video(640, 480); 19 | addChild(video); 20 | video.x = 0; 21 | video.y = 0; 22 | video.smoothing = true; 23 | video.attachNetStream(hls.stream); 24 | hls.addEventListener(HLSEvent.MANIFEST_LOADED, manifestHandler); 25 | hls.load("http://domain.com/hls/m1.m3u8"); 26 | } 27 | 28 | public function manifestHandler(event : HLSEvent) : void { 29 | hls.stream.play(null, -1); 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/flowplayer/HLSPluginFactory.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.flowplayer { 5 | import org.flowplayer.model.PluginFactory; 6 | 7 | import flash.display.Sprite; 8 | 9 | public class HLSPluginFactory extends Sprite implements PluginFactory { 10 | public function HLSPluginFactory() { 11 | } 12 | 13 | public function newPlugin() : Object { 14 | return new HLSStreamProvider(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/constant/HLSLoaderTypes.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.constant { 5 | /** Identifiers for the different stream types. **/ 6 | public class HLSLoaderTypes { 7 | // manifest loader 8 | public static const MANIFEST : int = 0; 9 | // playlist / level loader 10 | public static const LEVEL_MAIN : int = 1; 11 | // playlist / level loader 12 | public static const LEVEL_ALTAUDIO : int = 2; 13 | // main fragment loader 14 | public static const FRAGMENT_MAIN : int = 3; 15 | // alt audio fragment loader 16 | public static const FRAGMENT_ALTAUDIO : int = 4; 17 | } 18 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/constant/HLSMaxLevelCappingMode.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.constant { 5 | /** Max Level Capping Modes **/ 6 | public class HLSMaxLevelCappingMode { 7 | /** 8 | * max capped level should be the one with the dimensions equal or greater than the stage dimensions (so the video will be downscaled) 9 | */ 10 | public static const DOWNSCALE : String = "downscale"; 11 | 12 | /** 13 | * max capped level should be the one with the dimensions equal or lower than the stage dimensions (so the video will be upscaled) 14 | */ 15 | public static const UPSCALE : String = "upscale"; 16 | } 17 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/constant/HLSPlayStates.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.constant { 5 | /** Identifiers for the different playback states. **/ 6 | public class HLSPlayStates { 7 | /** idle state. **/ 8 | public static const IDLE : String = "IDLE"; 9 | /** playing state. **/ 10 | public static const PLAYING : String = "PLAYING"; 11 | /** paused state. **/ 12 | public static const PAUSED : String = "PAUSED"; 13 | /** playing/buffering state (playback is paused and will restart automatically as soon as buffer will contain enough data) **/ 14 | public static const PLAYING_BUFFERING : String = "PLAYING_BUFFERING"; 15 | /** paused/buffering state (playback is paused, and buffer is in low condition) **/ 16 | public static const PAUSED_BUFFERING : String = "PAUSED_BUFFERING"; 17 | } 18 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/constant/HLSSeekMode.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.constant { 5 | /** HLS Seek mode configuration **/ 6 | public class HLSSeekMode { 7 | /** seek on keyframe boundary **/ 8 | public static const KEYFRAME_SEEK : String = "KEYFRAME"; 9 | /** accurate seeking **/ 10 | public static const ACCURATE_SEEK : String = "ACCURATE"; 11 | } 12 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/constant/HLSSeekStates.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.constant { 5 | /** Identifiers for the different seeking states. **/ 6 | public class HLSSeekStates { 7 | /** idle state. **/ 8 | public static const IDLE : String = "IDLE"; 9 | /** seeking in progress state. **/ 10 | public static const SEEKING : String = "SEEKING"; 11 | /** seeked state. **/ 12 | public static const SEEKED : String = "SEEKED"; 13 | } 14 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/constant/HLSTypes.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.constant { 5 | /** Identifiers for the different stream types. **/ 6 | public class HLSTypes { 7 | /** Identifier for live events. **/ 8 | public static const LIVE : String = "LIVE"; 9 | /** Identifier for on demand clips. **/ 10 | public static const VOD : String = "VOD"; 11 | } 12 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/controller/BufferThresholdController.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.controller { 5 | import org.mangui.hls.constant.HLSLoaderTypes; 6 | import org.mangui.hls.event.HLSEvent; 7 | import org.mangui.hls.event.HLSLoadMetrics; 8 | import org.mangui.hls.HLS; 9 | import org.mangui.hls.HLSSettings; 10 | 11 | CONFIG::LOGGING { 12 | import org.mangui.hls.utils.Log; 13 | } 14 | /** Class that manages buffer threshold values (minBufferLength/lowBufferLength) 15 | */ 16 | public class BufferThresholdController { 17 | /** Reference to the HLS controller. **/ 18 | private var _hls : HLS; 19 | private var _targetduration : Number; 20 | private var _minBufferLength : Number; 21 | 22 | /** Create the loader. **/ 23 | public function BufferThresholdController(hls : HLS) : void { 24 | _hls = hls; 25 | _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler); 26 | _hls.addEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler); 27 | _hls.addEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler); 28 | }; 29 | 30 | public function dispose() : void { 31 | _hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler); 32 | _hls.removeEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler); 33 | _hls.removeEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler); 34 | } 35 | 36 | public function get minBufferLength() : Number { 37 | if (HLSSettings.minBufferLength == -1) { 38 | return _minBufferLength; 39 | } else { 40 | return HLSSettings.minBufferLength; 41 | } 42 | } 43 | 44 | public function get lowBufferLength() : Number { 45 | if (HLSSettings.minBufferLength == -1) { 46 | // in automode, low buffer threshold should be less than min auto buffer 47 | return Math.min(minBufferLength / 2, HLSSettings.lowBufferLength); 48 | } else { 49 | return HLSSettings.lowBufferLength; 50 | } 51 | } 52 | 53 | private function _manifestLoadedHandler(event : HLSEvent) : void { 54 | _targetduration = event.levels[_hls.startLevel].targetduration; 55 | _minBufferLength = _targetduration; 56 | }; 57 | 58 | private function _fragmentLoadedHandler(event : HLSEvent) : void { 59 | var metrics : HLSLoadMetrics = event.loadMetrics; 60 | // only monitor main fragment metrics for buffer threshold computing 61 | if(metrics.type == HLSLoaderTypes.FRAGMENT_MAIN) { 62 | /* set min buf len to be the time to process a complete segment, using current processing rate */ 63 | _minBufferLength = metrics.processing_duration * (_targetduration / metrics.duration); 64 | // avoid min > max 65 | if (HLSSettings.maxBufferLength) { 66 | _minBufferLength = Math.min(HLSSettings.maxBufferLength, _minBufferLength); 67 | } 68 | 69 | // avoid _minBufferLength > minBufferLengthCapping 70 | if (HLSSettings.minBufferLengthCapping > 0) { 71 | _minBufferLength = Math.min(HLSSettings.minBufferLengthCapping, _minBufferLength); 72 | } 73 | 74 | CONFIG::LOGGING { 75 | Log.debug2("AutoBufferController:minBufferLength:" + _minBufferLength); 76 | } 77 | }; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/demux/AVCC.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.demux { 5 | import flash.utils.ByteArray; 6 | CONFIG::LOGGING { 7 | import org.mangui.hls.utils.Log; 8 | import org.mangui.hls.HLSSettings; 9 | } 10 | public class AVCC { 11 | 12 | /** H264 profiles. **/ 13 | private static const PROFILES : Object = {'66':'H264 Baseline', '77':'H264 Main', '100':'H264 High'}; 14 | /** Get Avcc header from AVC stream 15 | See ISO 14496-15, 5.2.4.1 for the description of AVCDecoderConfigurationRecord 16 | **/ 17 | public static function getAVCC(sps : ByteArray, ppsVect : Vector.) : ByteArray { 18 | // Write startbyte 19 | var avcc : ByteArray = new ByteArray(); 20 | avcc.writeByte(0x01); 21 | // Write profile, compatibility and level. 22 | avcc.writeBytes(sps, 1, 3); 23 | // reserved (6 bits), NALU length size - 1 (2 bits) 24 | avcc.writeByte(0xFC | 3); 25 | // reserved (3 bits), num of SPS (5 bits) 26 | avcc.writeByte(0xE0 | 1); 27 | // 2 bytes for length of SPS 28 | avcc.writeShort(sps.length); 29 | // data of SPS 30 | avcc.writeBytes(sps, 0, sps.length); 31 | // Number of PPS 32 | avcc.writeByte(ppsVect.length); 33 | for each (var pps : ByteArray in ppsVect) { 34 | // 2 bytes for length of PPS 35 | avcc.writeShort(pps.length); 36 | // data of PPS 37 | avcc.writeBytes(pps, 0, pps.length); 38 | } 39 | CONFIG::LOGGING { 40 | if (HLSSettings.logDebug2) { 41 | // Grab profile/level 42 | sps.position = 1; 43 | var prf : int = sps.readByte(); 44 | sps.position = 3; 45 | var lvl : int = sps.readByte(); 46 | Log.debug("AVC: " + PROFILES[prf] + ' level ' + lvl); 47 | } 48 | } 49 | avcc.position = 0; 50 | return avcc; 51 | } 52 | ; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/demux/AudioFrame.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.demux { 5 | /** Audio Frame **/ 6 | public class AudioFrame { 7 | public var start : int; 8 | public var length : int; 9 | public var expected_length : int; 10 | public var rate : int; 11 | 12 | public function AudioFrame(start : int, length : int, expected_length : int, rate : int) { 13 | this.start = start; 14 | this.length = length; 15 | this.expected_length = expected_length; 16 | this.rate = rate; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/demux/DemuxHelper.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.demux { 5 | import flash.utils.ByteArray; 6 | import org.mangui.hls.model.Level; 7 | 8 | CONFIG::LOGGING { 9 | import org.mangui.hls.utils.Log; 10 | } 11 | public class DemuxHelper { 12 | public static function probe(data : ByteArray, 13 | level : Level, 14 | audioselect : Function, 15 | progress : Function, 16 | complete : Function, 17 | error : Function, 18 | videometadata : Function, 19 | id3tagfound : Function, 20 | audioOnly : Boolean) : Demuxer { 21 | data.position = 0; 22 | CONFIG::LOGGING { 23 | Log.debug("probe fragment type"); 24 | } 25 | var aac_match : Boolean = AACDemuxer.probe(data); 26 | var mp3_match : Boolean = MP3Demuxer.probe(data); 27 | var ts_match : Boolean = TSDemuxer.probe(data); 28 | CONFIG::LOGGING { 29 | Log.debug("AAC/MP3/TS match:" + aac_match + "/" + mp3_match + "/" + ts_match); 30 | } 31 | /* prioritize level info : 32 | * if ts_match && codec_avc => TS demuxer 33 | * if aac_match && codec_aac => AAC demuxer 34 | * if mp3_match && codec_mp3 => MP3 demuxer 35 | * if no codec info in Manifest, use fallback order : AAC/MP3/TS 36 | */ 37 | if (ts_match && level.codec_h264) { 38 | CONFIG::LOGGING { 39 | Log.debug("TS match + H264 signaled in Manifest, use TS demuxer"); 40 | } 41 | return new TSDemuxer(audioselect, progress, complete, error, videometadata, audioOnly); 42 | } else if (aac_match && level.codec_aac) { 43 | CONFIG::LOGGING { 44 | Log.debug("AAC match + AAC signaled in Manifest, use AAC demuxer"); 45 | } 46 | return new AACDemuxer(audioselect, progress, complete, error, id3tagfound); 47 | } else if (mp3_match && level.codec_mp3) { 48 | CONFIG::LOGGING { 49 | Log.debug("MP3 match + MP3 signaled in Manifest, use MP3 demuxer"); 50 | } 51 | return new MP3Demuxer(audioselect, progress, complete, error, id3tagfound); 52 | } else if (aac_match) { 53 | return new AACDemuxer(audioselect, progress, complete, error, id3tagfound); 54 | } else if (mp3_match) { 55 | return new MP3Demuxer(audioselect, progress, complete, error, id3tagfound); 56 | } else if (ts_match) { 57 | return new TSDemuxer(audioselect, progress, complete, error, videometadata, audioOnly); 58 | } else { 59 | CONFIG::LOGGING { 60 | Log.debug("probe fails"); 61 | } 62 | return null; 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/demux/Demuxer.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.demux { 5 | import flash.utils.ByteArray; 6 | 7 | public interface Demuxer { 8 | function append(data : ByteArray) : void; 9 | 10 | function notifycomplete() : void; 11 | 12 | function cancel() : void; 13 | 14 | function get audioExpected() : Boolean; 15 | 16 | function get videoExpected() : Boolean; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/demux/ExpGolomb.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.demux { 5 | import flash.utils.ByteArray; 6 | public class ExpGolomb { 7 | private var _data : ByteArray; 8 | private var _bit : int; 9 | private var _curByte : uint; 10 | 11 | public function ExpGolomb(data : ByteArray) { 12 | _data = data; 13 | _bit = -1; 14 | } 15 | 16 | private function _readBit() : uint { 17 | var res : uint; 18 | if (_bit == -1) { 19 | // read next 20 | _curByte = _data.readByte(); 21 | _bit = 7; 22 | } 23 | res = _curByte & (1 << _bit) ? 1 : 0; 24 | _bit--; 25 | return res; 26 | } 27 | 28 | public function readBoolean() : Boolean { 29 | return (_readBit() == 1); 30 | } 31 | 32 | public function readBits(nbBits : uint) : int { 33 | var val : int = 0; 34 | for (var i : uint = 0; i < nbBits; ++i) 35 | val = (val << 1) + _readBit(); 36 | return val; 37 | } 38 | 39 | public function readUE() : uint { 40 | var nbZero : uint = 0; 41 | while (_readBit() == 0) 42 | ++nbZero; 43 | var x : uint = readBits(nbZero); 44 | return x + (1 << nbZero) - 1; 45 | } 46 | 47 | public function readSE() : uint { 48 | var value : int = readUE(); 49 | // the number is odd if the low order bit is set 50 | if (0x01 & value) { 51 | // add 1 to make it even, and divide by 2 52 | return (1 + value) >> 1; 53 | } else { 54 | // divide by two then make it negative 55 | return -1 * (value >> 1); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/demux/ID3Tag.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.demux { 5 | /** Video Frame **/ 6 | public class ID3Tag { 7 | public var id : String; 8 | public var flag : int; 9 | public var base64 : Boolean; 10 | public var data : String; 11 | 12 | public function ID3Tag(id : String, flag : int, base64: Boolean, data : String) { 13 | this.id = id; 14 | this.flag = flag; 15 | this.base64 = base64; 16 | this.data = data; 17 | } 18 | 19 | public function toString(): String { 20 | return "id/flag/base64/data:" + id + '/' + flag + '/' + base64 + '/' + data; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/demux/PES.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.demux { 5 | import flash.utils.ByteArray; 6 | 7 | /** Representation of a Packetized Elementary Stream. **/ 8 | public class PES { 9 | /** The PES data (including headers). **/ 10 | public var data : ByteArray; 11 | /** PES prefix **/ 12 | public var prefix : uint; 13 | /** Start of the payload. **/ 14 | public var payload : uint; 15 | /** Timestamp from the PTS header. **/ 16 | public var pts : Number; 17 | /** Timestamp from the DTS header. **/ 18 | public var dts : Number; 19 | /** PES packet len **/ 20 | public var len : int; 21 | /** PES packet len **/ 22 | public var payload_len : int; 23 | 24 | /** Save the first chunk of PES data. **/ 25 | public function PES(dat : ByteArray) { 26 | data = dat; 27 | parse(); 28 | }; 29 | 30 | /** When all data is appended, parse the PES headers. **/ 31 | private function parse() : void { 32 | data.position = 0; 33 | // Start code prefix and packet ID. 34 | prefix = data.readUnsignedInt(); 35 | // read len 36 | len = data.readUnsignedShort(); 37 | // Ignore marker bits. 38 | data.position += 1; 39 | // Check for PTS 40 | var flags : uint = (data.readUnsignedByte() & 192) >> 6; 41 | // Check PES header length 42 | var length : uint = data.readUnsignedByte(); 43 | 44 | if (flags == 2 || flags == 3) { 45 | // Grab the timestamp from PTS data (spread out over 5 bytes): 46 | // XXXX---X -------- -------X -------- -------X 47 | 48 | var _pts : Number = Number((data.readUnsignedByte() & 0x0e)) * Number(1 << 29) + Number((data.readUnsignedShort() >> 1) << 15) + Number((data.readUnsignedShort() >> 1)); 49 | // check if greater than 2^32 -1 50 | if (_pts > 4294967295) { 51 | // decrement 2^33 52 | _pts -= 8589934592; 53 | } 54 | length -= 5; 55 | var _dts : Number = _pts; 56 | if (flags == 3) { 57 | // Grab the DTS (like PTS) 58 | _dts = Number((data.readUnsignedByte() & 0x0e)) * Number(1 << 29) + Number((data.readUnsignedShort() >> 1) << 15) + Number((data.readUnsignedShort() >> 1)); 59 | // check if greater than 2^32 -1 60 | if (_dts > 4294967295) { 61 | // decrement 2^33 62 | _dts -= 8589934592; 63 | } 64 | length -= 5; 65 | } 66 | pts = Math.round(_pts / 90); 67 | dts = Math.round(_dts / 90); 68 | // CONFIG::LOGGING { 69 | // Log.info("pts/dts: " + pts + "/"+ dts); 70 | // } 71 | } 72 | // Skip other header data and parse payload. 73 | data.position += length; 74 | payload = data.position; 75 | if (len) { 76 | payload_len = len - data.position + 6; 77 | } else { 78 | payload_len = 0; 79 | } 80 | }; 81 | } 82 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/demux/VideoFrame.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.demux { 5 | /** Video Frame **/ 6 | public class VideoFrame { 7 | public var header : int; 8 | public var start : int; 9 | public var length : int; 10 | public var type : int; 11 | 12 | public function VideoFrame(header : int, length : int, start : int, type : int) { 13 | this.header = header; 14 | this.start = start; 15 | this.length = length; 16 | this.type = type; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/event/HLSError.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.event { 5 | /** Error Identifier **/ 6 | public class HLSError { 7 | public static const OTHER_ERROR : int = 0; 8 | public static const MANIFEST_LOADING_CROSSDOMAIN_ERROR : int = 1; 9 | public static const MANIFEST_LOADING_IO_ERROR : int = 2; 10 | public static const MANIFEST_PARSING_ERROR : int = 3; 11 | public static const FRAGMENT_LOADING_CROSSDOMAIN_ERROR : int = 4; 12 | public static const FRAGMENT_LOADING_ERROR : int = 5; 13 | public static const FRAGMENT_PARSING_ERROR : int = 6; 14 | public static const KEY_LOADING_CROSSDOMAIN_ERROR : int = 7; 15 | public static const KEY_LOADING_ERROR : int = 8; 16 | public static const KEY_PARSING_ERROR : int = 9; 17 | public static const TAG_APPENDING_ERROR : int = 10; 18 | 19 | private var _code : int; 20 | private var _url : String; 21 | private var _msg : String; 22 | 23 | public function HLSError(code : int, url : String, msg : String) { 24 | _code = code; 25 | _url = url; 26 | _msg = msg; 27 | } 28 | 29 | public function get code() : int { 30 | return _code; 31 | } 32 | 33 | public function get msg() : String { 34 | return _msg; 35 | } 36 | 37 | public function get url() : String { 38 | return _url; 39 | } 40 | 41 | public function toString() : String { 42 | return "HLSError(code/url/msg)=" + _code + "/" + _url + "/" + _msg; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/event/HLSLoadMetrics.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.event { 5 | /** Fragment Loading metrics **/ 6 | public class HLSLoadMetrics { 7 | /* Loader Type : refer to HLSLoaderTypes for enumeration */ 8 | public var type : int; 9 | /* level of loaded content */ 10 | public var level : int; 11 | /* id of loaded content : should be SN for fragment, startSN for playlist */ 12 | public var id : int; 13 | /* id2 of loaded content : endSN for playlist, nb tags for tags loaded */ 14 | public var id2 : int; 15 | /** fragment/playlist size **/ 16 | public var size : int; 17 | /** fragment/playlist duration **/ 18 | public var duration : Number; 19 | /** loading request/start/end time **/ 20 | public var loading_request_time : int; 21 | public var loading_begin_time : int; 22 | public var loading_end_time : int; 23 | /** decryption begin/end time (for fragment only) **/ 24 | public var decryption_begin_time : int; 25 | public var decryption_end_time : int; 26 | /** parsing begin/end time (for fragment only) */ 27 | public var parsing_begin_time : int; 28 | public var parsing_end_time : int; 29 | 30 | public function HLSLoadMetrics(type : int) { 31 | this.type = type; 32 | } 33 | 34 | public function get bandwidth() : int { 35 | return size * 8000 / (parsing_end_time - loading_request_time); 36 | } 37 | 38 | public function get processing_duration() : int { 39 | return parsing_end_time-loading_request_time; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/event/HLSMediatime.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.event { 5 | /** Identifiers for the different stream types. **/ 6 | public class HLSMediatime { 7 | /** playback position (in seconds), relative to current playlist start. 8 | * this value could be negative in case of live playlist sliding : 9 | * this can happen in case current playback position 10 | * is in a fragment that has been removed from the playlist 11 | */ 12 | public var position : Number; 13 | /** current playlist duration (in seconds) **/ 14 | public var duration : Number; 15 | /** live main playlist sliding since previous out of buffer seek() (in seconds)**/ 16 | public var live_sliding_main : Number; 17 | /** live altaudio playlist sliding since previous out of buffer seek() (in seconds)**/ 18 | public var live_sliding_altaudio : Number; 19 | /** current buffer duration (in seconds) **/ 20 | public var buffer : Number; 21 | /** current buffer duration (in seconds) **/ 22 | public var backbuffer : Number; 23 | /** total watched duration (in seconds) since hls.load(URL) **/ 24 | public var watched : Number; 25 | 26 | public function HLSMediatime(position : Number, duration : Number, buffer : Number, backbuffer : Number, live_sliding_main : Number, live_sliding_altaudio : Number, watched : Number) { 27 | this.position = position; 28 | this.duration = duration; 29 | this.buffer = buffer; 30 | this.backbuffer = backbuffer; 31 | this.live_sliding_main = live_sliding_main; 32 | this.live_sliding_altaudio = live_sliding_altaudio; 33 | this.watched = watched; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/event/HLSPlayMetrics.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.event { 5 | /** playback metrics, notified when playback of a given fragment starts **/ 6 | public class HLSPlayMetrics { 7 | public var level : int; 8 | public var seqnum : int; 9 | public var continuity_counter : int; 10 | public var duration : Number; 11 | public var audio_only : Boolean; 12 | public var program_date : Number; 13 | public var video_width : int; 14 | public var video_height : int; 15 | public var auto_level : Boolean; 16 | public var tag_list : Array; 17 | public var id3tag_list : Array; 18 | 19 | public function HLSPlayMetrics(level : int, seqnum : int, cc : int, duration : Number, audio_only : Boolean, program_date : Number, video_width : int, video_height : int, auto_level : Boolean, tag_list : Array, id3tag_list : Array) { 20 | this.level = level; 21 | this.seqnum = seqnum; 22 | this.continuity_counter = cc; 23 | this.duration = duration; 24 | this.audio_only = audio_only; 25 | this.program_date = program_date; 26 | this.video_width = video_width; 27 | this.video_height = video_height; 28 | this.auto_level = auto_level; 29 | this.tag_list = tag_list; 30 | this.id3tag_list = id3tag_list; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/model/AudioTrack.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.model { 5 | /** Audio Track identifier **/ 6 | public class AudioTrack { 7 | public static const FROM_DEMUX : int = 0; 8 | public static const FROM_PLAYLIST : int = 1; 9 | public var title : String; 10 | public var id : int; 11 | public var source : int; 12 | public var isDefault : Boolean; 13 | public var isAAC : Boolean; 14 | public var level : Level; 15 | 16 | public function AudioTrack(title : String, source : int, id : int, isDefault : Boolean, isAAC : Boolean) { 17 | this.title = title; 18 | this.source = source; 19 | this.id = id; 20 | this.isDefault = isDefault; 21 | this.isAAC = isAAC; 22 | } 23 | 24 | public function toString() : String { 25 | return "AudioTrack ID: " + id + " Title: " + title + " Source: " + source + " Default: " + isDefault + " AAC: " + isAAC; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/playlist/AltAudioTrack.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.playlist { 5 | public class AltAudioTrack { 6 | public var group_id : String; 7 | public var lang : String; 8 | public var name : String; 9 | public var autoselect : Boolean; 10 | public var default_track : Boolean; 11 | public var url : String; 12 | 13 | /** Create the quality level. **/ 14 | public function AltAudioTrack(alt_group_id : String, alt_lang : String, alt_name : String, alt_autoselect : Boolean, alt_default : Boolean, alt_url : String) { 15 | group_id = alt_group_id; 16 | lang = alt_lang; 17 | name = alt_name; 18 | autoselect = alt_autoselect; 19 | default_track = alt_default; 20 | url = alt_url; 21 | }; 22 | 23 | public function toString() : String { 24 | return "AltAudioTrack url: " + url + " group_id: " + group_id + " lang: " + lang + " name: " + name + ' default: ' + default_track ; 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/playlist/DataUri.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.playlist { 5 | CONFIG::LOGGING { 6 | import org.mangui.hls.utils.Log; 7 | } 8 | 9 | /** 10 | * Facilitates extracting information from a data URI. 11 | */ 12 | public class DataUri { 13 | 14 | private static const DATA_PROTOCOL : String = "data:"; 15 | private static const BASE_64 : String = "base64"; 16 | 17 | private var _dataUri : String; 18 | 19 | public function DataUri(dataUri : String) { 20 | _dataUri = dataUri; 21 | } 22 | 23 | /** 24 | * @return Returns the data portion of the data URI if it is able extract the information, 25 | * null otherwise. 26 | */ 27 | public function extractData() : String { 28 | if (_dataUri == null) { 29 | return null; 30 | } 31 | 32 | var base64Index : int = _dataUri.indexOf(BASE_64 + ','); 33 | var dataIndex : int = _dataUri.indexOf(',') + 1; 34 | 35 | if (dataIndex > _dataUri.length) { 36 | return null; 37 | } 38 | 39 | var data : String = _dataUri.substr(dataIndex); 40 | return (base64Index === -1) ? _extractPlainData(data) : _extractBase64Data(data); 41 | } 42 | 43 | /** 44 | * Data URIs support base 64 encoding the data section. 45 | * This is not typically used for plain text files, which includes HLS manifests. 46 | * As such, decoded base 64 data sections is not currently (6/18/14) supported. 47 | * @param data 48 | * @return 49 | */ 50 | private function _extractBase64Data(data : String) : String { 51 | CONFIG::LOGGING { 52 | Log.warn("Base 64 encoded Data URIs are not supported."); 53 | } 54 | return null; 55 | } 56 | 57 | /** 58 | * @param data 59 | * @return The URL decoded data section from the data URI. 60 | */ 61 | private function _extractPlainData(data : String) : String { 62 | var decodedData : String = decodeURIComponent(data); 63 | CONFIG::LOGGING { 64 | Log.debug2("Decoded data from data URI into: " + decodedData); 65 | } 66 | return decodedData; 67 | } 68 | 69 | /** 70 | * @param dataUri 71 | * @return True if the provided string is a data URI, false otherwise. 72 | */ 73 | public static function isDataUri(dataUri : String) : Boolean { 74 | return dataUri != null && dataUri.indexOf(DATA_PROTOCOL) === 0; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/stream/HLSNetStreamClient.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.stream { 5 | import flash.utils.flash_proxy; 6 | import flash.utils.Proxy; 7 | 8 | /** Proxy that allows dispatching internal events fired by Netstream cues to 9 | * internal listeners as well as the traditional client object 10 | */ 11 | public class HLSNetStreamClient extends Proxy { 12 | private var _delegate : Object; 13 | private var _callbacks : Object = new Object(); 14 | 15 | public function HLSNetStreamClient() { 16 | } 17 | 18 | public function set delegate(client : Object) : void { 19 | this._delegate = client; 20 | } 21 | 22 | public function get delegate() : Object { 23 | return this._delegate; 24 | } 25 | 26 | public function registerCallback(name : String, callback : Function) : void { 27 | _callbacks[name] = callback; 28 | } 29 | 30 | override flash_proxy function callProperty(methodName : *, ... args) : * { 31 | var r : * = null; 32 | 33 | if (_callbacks && _callbacks.hasOwnProperty(methodName)) { 34 | r = _callbacks[methodName](args); 35 | } 36 | 37 | if (_delegate && _delegate.hasOwnProperty(methodName)) { 38 | r = _delegate[methodName](args); 39 | } 40 | 41 | return r; 42 | } 43 | 44 | override flash_proxy function getProperty(name : *) : * { 45 | var r : *; 46 | if (_callbacks && _callbacks.hasOwnProperty(name)) { 47 | r = _callbacks[name]; 48 | } 49 | 50 | if (_delegate && _delegate.hasOwnProperty(name)) { 51 | r = _delegate[name]; 52 | } 53 | 54 | return r; 55 | } 56 | 57 | override flash_proxy function hasProperty(name : *) : Boolean { 58 | return (_delegate && _delegate.hasOwnProperty(name)) || _callbacks.hasOwnProperty(name); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/utils/DateUtil.as: -------------------------------------------------------------------------------- 1 | /** 2 | * DateUtil 3 | * 4 | * inspired by https://code.google.com/p/as3corelib/source/browse/trunk/src/com/adobe/utils/DateUtil.as#531 5 | */ 6 | package org.mangui.hls.utils { 7 | 8 | public class DateUtil { 9 | public static function parseW3CDTF(str:String):Date 10 | { 11 | var finalDate:Date; 12 | try 13 | { 14 | var dateStr:String = str.substring(0, str.indexOf("T")); 15 | var timeStr:String = str.substring(str.indexOf("T")+1, str.length); 16 | var dateArr:Array = dateStr.split("-"); 17 | var year:Number = Number(dateArr.shift()); 18 | var month:Number = Number(dateArr.shift()); 19 | var date:Number = Number(dateArr.shift()); 20 | 21 | var multiplier:Number; 22 | var offsetHours:Number; 23 | var offsetMinutes:Number; 24 | var offsetStr:String; 25 | 26 | if (timeStr.indexOf("Z") != -1) 27 | { 28 | multiplier = 1; 29 | offsetHours = 0; 30 | offsetMinutes = 0; 31 | timeStr = timeStr.replace("Z", ""); 32 | } 33 | else if (timeStr.indexOf("+") != -1) 34 | { 35 | multiplier = 1; 36 | offsetStr = timeStr.substring(timeStr.indexOf("+")+1, timeStr.length); 37 | offsetHours = Number(offsetStr.substring(0, offsetStr.indexOf(":"))); 38 | offsetMinutes = Number(offsetStr.substring(offsetStr.indexOf(":")+1, offsetStr.length)); 39 | timeStr = timeStr.substring(0, timeStr.indexOf("+")); 40 | } 41 | else // offset is - 42 | { 43 | multiplier = -1; 44 | offsetStr = timeStr.substring(timeStr.indexOf("-")+1, timeStr.length); 45 | offsetHours = Number(offsetStr.substring(0, offsetStr.indexOf(":"))); 46 | offsetMinutes = Number(offsetStr.substring(offsetStr.indexOf(":")+1, offsetStr.length)); 47 | timeStr = timeStr.substring(0, timeStr.indexOf("-")); 48 | } 49 | var timeArr:Array = timeStr.split(":"); 50 | var hour:Number = Number(timeArr.shift()); 51 | var minutes:Number = Number(timeArr.shift()); 52 | var secondsArr:Array = (timeArr.length > 0) ? String(timeArr.shift()).split(".") : null; 53 | var seconds:Number = (secondsArr != null && secondsArr.length > 0) ? Number(secondsArr.shift()) : 0; 54 | //var milliseconds:Number = (secondsArr != null && secondsArr.length > 0) ? Number(secondsArr.shift()) : 0; 55 | 56 | var milliseconds:Number = (secondsArr != null && secondsArr.length > 0) ? 1000*parseFloat("0." + secondsArr.shift()) : 0; 57 | var utc:Number = Date.UTC(year, month-1, date, hour, minutes, seconds, milliseconds); 58 | var offset:Number = (((offsetHours * 3600000) + (offsetMinutes * 60000)) * multiplier); 59 | finalDate = new Date(utc - offset); 60 | 61 | if (finalDate.toString() == "Invalid Date") 62 | { 63 | throw new Error("This date does not conform to W3CDTF."); 64 | } 65 | } 66 | catch (e:Error) 67 | { 68 | var eStr:String = "Unable to parse the string [" +str+ "] into a date. "; 69 | eStr += "The internal error was: " + e.toString(); 70 | throw new Error(eStr); 71 | } 72 | return finalDate; 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/utils/Hex.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Hex 3 | * 4 | * Utility class to convert Hex strings to ByteArray or String types. 5 | * Copyright (c) 2007 Henri Torgemane 6 | * 7 | * See LICENSE.txt for full license information. 8 | */ 9 | package org.mangui.hls.utils { 10 | import flash.utils.ByteArray; 11 | 12 | public class Hex { 13 | /** 14 | * Generates byte-array from given hexadecimal string 15 | * 16 | * Supports straight and colon-laced hex (that means 23:03:0e:f0, but *NOT* 23:3:e:f0) 17 | * The first nibble (hex digit) may be omitted. 18 | * Any whitespace characters are ignored. 19 | */ 20 | public static function toArray(hex : String) : ByteArray { 21 | hex = hex.replace(/^0x|\s|:/gm, ''); 22 | var a : ByteArray = new ByteArray; 23 | var len : uint = hex.length; 24 | if ((len & 1) == 1) hex = "0" + hex; 25 | for (var i : uint = 0; i < len; i += 2) { 26 | a[i / 2] = parseInt(hex.substr(i, 2), 16); 27 | } 28 | return a; 29 | } 30 | 31 | /** 32 | * Generates lowercase hexadecimal string from given byte-array 33 | */ 34 | public static function fromArray(array : ByteArray, colons : Boolean = false) : String { 35 | var s : String = ""; 36 | var len : uint = array.length; 37 | for (var i : uint = 0; i < len; i++) { 38 | s += ("0" + array[i].toString(16)).substr(-2, 2); 39 | if (colons) { 40 | if (i < len - 1) s += ":"; 41 | } 42 | } 43 | return s; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/utils/JSURLLoader.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.utils { 5 | import org.mangui.hls.HLS; 6 | import flash.events.Event; 7 | import flash.events.IOErrorEvent; 8 | import flash.events.ProgressEvent; 9 | import flash.events.TimerEvent; 10 | import flash.external.ExternalInterface; 11 | import flash.net.URLRequest; 12 | import flash.net.URLLoader; 13 | 14 | CONFIG::LOGGING { 15 | import org.mangui.hls.utils.Log; 16 | } 17 | 18 | // Playlist Loader 19 | public dynamic class JSURLLoader extends URLLoader { 20 | private var _resource : String = new String(); 21 | /* callback names */ 22 | private var _callbackLoaded : String; 23 | private var _callbackFailure : String; 24 | private static var _instanceCount : int = 0; 25 | /** JS callbacks prefix */ 26 | protected static var _callbackName : String = 'JSLoaderPlaylist'; 27 | 28 | public function JSURLLoader() { 29 | ExternalInterface.marshallExceptions = true; 30 | super(); 31 | 32 | // Connect calls to JS. 33 | if (ExternalInterface.available) { 34 | CONFIG::LOGGING { 35 | Log.debug("add callback textLoaded, id:" + _instanceCount); 36 | } 37 | _callbackLoaded = "textLoaded" + _instanceCount; 38 | _callbackFailure = "textLoadingError" + _instanceCount; 39 | // dynamically register callbacks 40 | this[_callbackLoaded] = function(res:String): void { resourceLoaded(res)}; 41 | this[_callbackFailure] = function() : void { resourceLoadingError()}; 42 | ExternalInterface.addCallback(_callbackLoaded, this[_callbackLoaded]); 43 | ExternalInterface.addCallback(_callbackFailure, this[_callbackFailure]); 44 | _instanceCount++; 45 | } 46 | } 47 | 48 | public static function set externalCallback(callbackName: String) : void { 49 | _callbackName = callbackName; 50 | } 51 | 52 | protected function _trigger(event : String, ...args) : void { 53 | if (ExternalInterface.available) { 54 | ExternalInterface.call(_callbackName, event, args); 55 | } 56 | } 57 | 58 | override public function close() : void { 59 | if (ExternalInterface.available) { 60 | _trigger('abortPlaylist', ExternalInterface.objectID); 61 | } else { 62 | super.close(); 63 | } 64 | } 65 | 66 | override public function load(request : URLRequest) : void { 67 | CONFIG::LOGGING { 68 | Log.debug("JSURLLoader.load:" + request.url); 69 | } 70 | bytesLoaded = bytesTotal = 0; 71 | data = null; 72 | if (ExternalInterface.available) { 73 | _trigger('requestPlaylist', ExternalInterface.objectID, request.url, _callbackLoaded, _callbackFailure); 74 | this.dispatchEvent(new Event(Event.OPEN)); 75 | } else { 76 | super.load(request); 77 | } 78 | } 79 | 80 | protected function resourceLoaded(resource : String) : void { 81 | CONFIG::LOGGING { 82 | Log.debug("resourceLoaded"); 83 | } 84 | data = resource; 85 | bytesLoaded = bytesTotal = resource.length; 86 | this.dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, bytesLoaded, bytesTotal)); 87 | this.dispatchEvent(new Event(Event.COMPLETE)); 88 | } 89 | 90 | protected function resourceLoadingError() : void { 91 | CONFIG::LOGGING { 92 | Log.debug("resourceLoadingError"); 93 | } 94 | this.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR)); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/utils/Log.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.utils { 5 | import flash.external.ExternalInterface; 6 | 7 | import org.mangui.hls.HLSSettings; 8 | 9 | /** Class that sends log messages to browser console. **/ 10 | public class Log { 11 | private static const LEVEL_INFO : String = "INFO:"; 12 | private static const LEVEL_DEBUG : String = "DEBUG:"; 13 | private static const LEVEL_WARN : String = "WARN:"; 14 | private static const LEVEL_ERROR : String = "ERROR:"; 15 | 16 | public static function info(message : *) : void { 17 | if (HLSSettings.logInfo) 18 | outputlog(LEVEL_INFO, String(message)); 19 | }; 20 | 21 | public static function debug(message : *) : void { 22 | if (HLSSettings.logDebug) 23 | outputlog(LEVEL_DEBUG, String(message)); 24 | }; 25 | 26 | public static function debug2(message : *) : void { 27 | if (HLSSettings.logDebug2) 28 | outputlog(LEVEL_DEBUG, String(message)); 29 | }; 30 | 31 | public static function warn(message : *) : void { 32 | if (HLSSettings.logWarn) 33 | outputlog(LEVEL_WARN, String(message)); 34 | }; 35 | 36 | public static function error(message : *) : void { 37 | if (HLSSettings.logError) 38 | outputlog(LEVEL_ERROR, String(message)); 39 | }; 40 | 41 | /** Log a message to the console. **/ 42 | private static function outputlog(level : String, message : String) : void { 43 | if (ExternalInterface.available) 44 | ExternalInterface.call('console.log', level + message); 45 | else trace(level + message); 46 | } 47 | }; 48 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/utils/PTS.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.utils { 5 | public class PTS { 6 | /* find PTS value nearest a given reference PTS value 7 | * 8 | * PTS retrieved from demux are within a range of 9 | * (+/-) 2^32/90 - 1 = (+/-) 47721858 10 | * when reaching upper limit, PTS will loop to lower limit 11 | * this cause some issues with fragment duration calculation 12 | * this method will normalize a given PTS value and output a result 13 | * that is closest to provided PTS reference value. 14 | * i.e it could output values bigger than the (+/-) 2^32/90. 15 | * this will avoid PTS looping issues. 16 | */ 17 | public static function normalize(reference : Number, value : Number) : Number { 18 | var offset : Number; 19 | if (reference < value) { 20 | // - 2^33/90 21 | offset = -95443717; 22 | } else { 23 | // + 2^33/90 24 | offset = 95443717; 25 | } 26 | // 2^32 / 90 27 | while (!isNaN(reference) && (Math.abs(value - reference) > 47721858)) { 28 | value += offset; 29 | } 30 | return value; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/utils/Params2Settings.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.utils { 5 | import org.mangui.hls.HLSSettings; 6 | 7 | import flash.utils.describeType; 8 | import flash.utils.Dictionary; 9 | import flash.utils.getDefinitionByName; 10 | import flash.utils.getQualifiedClassName; 11 | 12 | /** 13 | * Params2Settings is an helper class that holds every legal external params names 14 | * which can be used to customize HLSSettings and maps them to the relevant HLSSettings values 15 | */ 16 | public class Params2Settings { 17 | /** 18 | * HLSSettings <-> params maping 19 | */ 20 | private static var _paramMap : Dictionary = new Dictionary(); 21 | 22 | // static initializer 23 | { 24 | _initParams(); 25 | } 26 | 27 | 28 | /* build map between param name and HLSSettings property 29 | this is done by enumerating properties : http://stackoverflow.com/questions/13294997/as3-iterating-through-class-variables 30 | */ 31 | private static function _initParams() : void { 32 | var description:XML = describeType(HLSSettings); 33 | var variables:XMLList = description..variable; 34 | for each(var variable:XML in variables) { 35 | var name : String = variable.@name; 36 | var param : String; 37 | if(name.indexOf("log") == 0) { 38 | // loggers params don't need prefix 39 | param = name.substr(3); 40 | } else { 41 | param = name; 42 | } 43 | // for historical (bad ?) reasons, param names are lowercase 44 | param = param.toLowerCase(); 45 | _paramMap[param] = name; 46 | } 47 | } 48 | 49 | public static function set(key : String, value : Object) : void { 50 | var param : String = _paramMap[key]; 51 | if (param) { 52 | // try to assign value with proper object type 53 | try { 54 | var cName : String = getQualifiedClassName(HLSSettings[param]); 55 | // AS3 bug: "getDefinitionByName" considers var value, not type, and wrongly (e.g. 3.0 >> "int"; 3.1 >> "Number"). 56 | var c : Class = cName === "int" ? Number : getDefinitionByName(cName) as Class; 57 | 58 | // only set booleans to true if the string actually is true, otherwise false 59 | if(cName === "Boolean") { 60 | HLSSettings[param] = String(value).toLowerCase() === "true"; 61 | } else { // Otherwise just cast it 62 | HLSSettings[param] = c(value); 63 | } 64 | 65 | CONFIG::LOGGING { 66 | Log.info("HLSSettings." + param + " = " + HLSSettings[param]); 67 | } 68 | } catch(error : Error) { 69 | CONFIG::LOGGING { 70 | Log.warn("Can't set HLSSettings." + param); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/utils/ScaleVideo.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.hls.utils { 5 | import flash.geom.Rectangle; 6 | 7 | public class ScaleVideo { 8 | public static function resizeRectangle(videoWidth : int, videoHeight : int, containerWidth : int, containerHeight : int) : Rectangle { 9 | var rect : Rectangle = new Rectangle(); 10 | var xscale : Number = containerWidth / videoWidth; 11 | var yscale : Number = containerHeight / videoHeight; 12 | if (xscale >= yscale) { 13 | rect.width = Math.min(videoWidth * yscale, containerWidth); 14 | rect.height = videoHeight * yscale; 15 | } else { 16 | rect.width = Math.min(videoWidth * xscale, containerWidth); 17 | rect.height = videoHeight * xscale; 18 | } 19 | rect.width = Math.ceil(rect.width); 20 | rect.height = Math.ceil(rect.height); 21 | rect.x = Math.round((containerWidth - rect.width) / 2); 22 | rect.y = Math.round((containerHeight - rect.height) / 2); 23 | CONFIG::LOGGING { 24 | Log.debug("width:" + rect.width); 25 | Log.debug("height:" + rect.height); 26 | Log.debug("x:" + rect.x); 27 | Log.debug("y:" + rect.y); 28 | } 29 | return rect; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/hls/utils/StringUtil.as: -------------------------------------------------------------------------------- 1 | package org.mangui.hls.utils 2 | { 3 | public class StringUtil 4 | { 5 | /** 6 | * Returns true if the specified string is 7 | * a single space, tab, carriage return, newline, or formfeed character. 8 | * 9 | * @param str The String that is is being queried. 10 | * 11 | * @return true if the specified string is 12 | * a single space, tab, carriage return, newline, or formfeed character. 13 | */ 14 | public static function isWhitespace(character:String):Boolean 15 | { 16 | switch (character) 17 | { 18 | case " ": 19 | case "\t": 20 | case "\r": 21 | case "\n": 22 | case "\f": 23 | case "\u00A0": // non breaking space 24 | case "\u2028": // line seperator 25 | case "\u2029": // paragraph seperator 26 | case "\u3000": // ideographic space 27 | return true; 28 | } 29 | 30 | return false; 31 | } 32 | 33 | /** 34 | * Removes all whitespace characters from the beginning and end 35 | * of the specified string. 36 | * 37 | * @param str The String whose whitespace should be trimmed. 38 | * 39 | * @return Updated String where whitespace was removed from the 40 | * beginning and end. 41 | */ 42 | public static function trim(str:String):String 43 | { 44 | if (str == null) return ''; 45 | 46 | var startIndex:int = 0; 47 | while (isWhitespace(str.charAt(startIndex))) 48 | ++startIndex; 49 | 50 | var endIndex:int = str.length - 1; 51 | while (isWhitespace(str.charAt(endIndex))) 52 | --endIndex; 53 | 54 | if (endIndex >= startIndex) 55 | return str.slice(startIndex, endIndex + 1); 56 | else 57 | return ""; 58 | } 59 | 60 | /** 61 | * Splits a String into an Vector of nicely trimmed strings, where each 62 | * item represents a single line of the original String data 63 | * 64 | * @param str The String to be split into an Array 65 | * @return Vector of type String 66 | */ 67 | public static function toLines(str:String):Vector. 68 | { 69 | var lines:Array = toLF(str).split("\n"); 70 | var i:uint; 71 | var length:uint = lines.length; 72 | 73 | for (i=0; i(lines); 79 | } 80 | 81 | /** 82 | * Converts strings containing Windows (CR-LF), MacOS (CR) and other 83 | * non-standard line breaks (LF-CR) into strings using only Linux-style 84 | * line breaks (LF). 85 | * 86 | * @param str String containing non-Linux line breaks 87 | * @returns String containly only Linux-style line breaks 88 | */ 89 | public static function toLF(str:String):String 90 | { 91 | return (str || "").replace(/\r\n|\n\r|\r/g, "\n"); 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/HLSDynamicPlugin.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins { 5 | import flash.display.Sprite; 6 | import flash.system.Security; 7 | 8 | import org.osmf.media.PluginInfo; 9 | 10 | public class HLSDynamicPlugin extends Sprite { 11 | private var _pluginInfo : PluginInfo; 12 | 13 | public function HLSDynamicPlugin() { 14 | super(); 15 | Security.allowDomain("*"); 16 | _pluginInfo = new HLSPlugin(); 17 | } 18 | 19 | public function get pluginInfo() : PluginInfo { 20 | return _pluginInfo; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/HLSPlugin.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins { 5 | import org.mangui.hls.utils.Params2Settings; 6 | import org.mangui.osmf.plugins.loader.HLSLoaderBase; 7 | import org.mangui.osmf.plugins.loader.HLSLoadFromDocumentElement; 8 | import org.osmf.media.MediaElement; 9 | import org.osmf.media.MediaFactoryItem; 10 | import org.osmf.media.MediaFactoryItemType; 11 | import org.osmf.media.MediaResourceBase; 12 | import org.osmf.media.PluginInfo; 13 | 14 | CONFIG::LOGGING { 15 | import org.mangui.hls.utils.Log; 16 | } 17 | 18 | public class HLSPlugin extends PluginInfo { 19 | public function HLSPlugin(items : Vector.=null, elementCreatedNotification : Function = null) { 20 | items = new Vector.(); 21 | items.push(new MediaFactoryItem('org.mangui.osmf.plugins.HLSPlugin', canHandleResource, createMediaElement, MediaFactoryItemType.STANDARD)); 22 | 23 | super(items, elementCreatedNotification); 24 | } 25 | 26 | /** 27 | * Called from super class when plugin has been initialized with the MediaFactory from which it was loaded. 28 | * Used for customize HLSSettings with values provided in resource metadata (that was set eg. in flash vars) 29 | * 30 | * @param resource Provides access to the resource used to load the plugin and any associated metadata 31 | * 32 | */ 33 | override public function initializePlugin(resource : MediaResourceBase) : void { 34 | CONFIG::LOGGING { 35 | Log.debug("OSMF HLSPlugin init"); 36 | } 37 | metadataParamsToHLSSettings(resource); 38 | } 39 | 40 | private function canHandleResource(resource : MediaResourceBase) : Boolean { 41 | return HLSLoaderBase.canHandle(resource); 42 | } 43 | 44 | private function createMediaElement() : MediaElement { 45 | return new HLSLoadFromDocumentElement(null, new HLSLoaderBase()); 46 | } 47 | 48 | private function metadataParamsToHLSSettings(resource : MediaResourceBase) : void { 49 | if (resource == null) { 50 | return; 51 | } 52 | 53 | var metadataNamespaceURLs : Vector. = resource.metadataNamespaceURLs; 54 | 55 | // set all legal params values to HLSSettings properties 56 | for each (var key : String in metadataNamespaceURLs) { 57 | Params2Settings.set(key, resource.getMetadataValue(key)); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/loader/HLSNetLoader.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.loader { 5 | import flash.net.NetStream; 6 | import flash.net.NetConnection; 7 | 8 | import org.osmf.net.NetLoader; 9 | import org.osmf.media.URLResource; 10 | import org.mangui.hls.HLS; 11 | 12 | public class HLSNetLoader extends NetLoader { 13 | private var _hls : HLS; 14 | private var _connection : NetConnection; 15 | private var _resource : URLResource; 16 | 17 | public function HLSNetLoader(hls : HLS) { 18 | _hls = hls; 19 | super(); 20 | } 21 | 22 | override protected function createNetStream(connection : NetConnection, resource : URLResource) : NetStream { 23 | _connection = connection; 24 | _resource = resource; 25 | return _hls.stream; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSBufferTrait.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.traits { 5 | import org.mangui.hls.HLS; 6 | import org.mangui.hls.event.HLSEvent; 7 | import org.mangui.hls.constant.HLSPlayStates; 8 | import org.osmf.traits.BufferTrait; 9 | 10 | CONFIG::LOGGING { 11 | import org.mangui.hls.utils.Log; 12 | } 13 | 14 | public class HLSBufferTrait extends BufferTrait { 15 | private var _hls : HLS; 16 | 17 | public function HLSBufferTrait(hls : HLS) { 18 | CONFIG::LOGGING { 19 | Log.debug("HLSBufferTrait()"); 20 | } 21 | super(); 22 | _hls = hls; 23 | _hls.addEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler); 24 | } 25 | 26 | override public function dispose() : void { 27 | CONFIG::LOGGING { 28 | Log.debug("HLSBufferTrait:dispose"); 29 | } 30 | _hls.removeEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler); 31 | super.dispose(); 32 | } 33 | 34 | override public function get bufferLength() : Number { 35 | return _hls.stream.bufferLength; 36 | } 37 | 38 | /** state changed handler **/ 39 | private function _stateChangedHandler(event : HLSEvent) : void { 40 | switch(event.state) { 41 | case HLSPlayStates.PLAYING_BUFFERING: 42 | case HLSPlayStates.PAUSED_BUFFERING: 43 | CONFIG::LOGGING { 44 | Log.debug("HLSBufferTrait:_stateChangedHandler:setBuffering(true)"); 45 | } 46 | setBuffering(true); 47 | break; 48 | default: 49 | CONFIG::LOGGING { 50 | Log.debug("HLSBufferTrait:_stateChangedHandler:setBuffering(false)"); 51 | } 52 | setBuffering(false); 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSClosedCaptionsState.as: -------------------------------------------------------------------------------- 1 | package org.mangui.osmf.plugins.traits 2 | { 3 | public final class HLSClosedCaptionsState 4 | { 5 | public static const YES:String = "yes"; 6 | public static const NO:String = "no"; 7 | public static const UNKNOWN:String = "unknown"; 8 | } 9 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSClosedCaptionsTrait.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.traits { 5 | import org.mangui.hls.HLS; 6 | import org.mangui.hls.event.HLSEvent; 7 | import org.mangui.hls.model.Level; 8 | import org.osmf.traits.MediaTraitBase; 9 | 10 | CONFIG::LOGGING { 11 | import org.mangui.hls.utils.Log; 12 | } 13 | 14 | public class HLSClosedCaptionsTrait extends MediaTraitBase { 15 | private var _hls : HLS; 16 | private var _hasClosedCapations : String; 17 | 18 | public function HLSClosedCaptionsTrait(hls : HLS, closed_captions : String = HLSClosedCaptionsState.UNKNOWN) { 19 | CONFIG::LOGGING { 20 | Log.debug("HLSClosedCaptionsTrait()"); 21 | } 22 | super(HLSMediaTraitType.CLOSED_CAPTIONS); 23 | 24 | _hasClosedCapations = closed_captions; 25 | _hls = hls; 26 | _hls.addEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler); 27 | } 28 | 29 | override public function dispose() : void { 30 | CONFIG::LOGGING { 31 | Log.debug("HLSClosedCaptionsTrait:dispose"); 32 | } 33 | _hls.removeEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler); 34 | super.dispose(); 35 | } 36 | 37 | public function hasClosedCaptions() : String { 38 | return _hasClosedCapations; 39 | } 40 | 41 | /** Update playback position/duration **/ 42 | private function _levelSwitchHandler(event : HLSEvent) : void { 43 | var cc : String = (_hls.levels[event.level] as Level).closed_captions; 44 | 45 | if (cc && cc === "NONE") 46 | { 47 | // manifest told us to ignore any 608/708 binary 48 | _hasClosedCapations = HLSClosedCaptionsState.NO; 49 | } 50 | else 51 | { 52 | _hasClosedCapations = HLSClosedCaptionsState.UNKNOWN; 53 | } 54 | 55 | // YES only happens for WebVTT, which isn't supported. 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSDisplayObjectTrait.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.traits { 5 | 6 | import flash.display.DisplayObject; 7 | import flash.display.Stage; 8 | import flash.events.Event; 9 | 10 | import org.mangui.hls.HLS; 11 | import org.osmf.media.videoClasses.VideoSurface; 12 | import org.osmf.traits.DisplayObjectTrait; 13 | 14 | CONFIG::LOGGING { 15 | import org.mangui.hls.utils.Log; 16 | } 17 | 18 | public class HLSDisplayObjectTrait extends DisplayObjectTrait { 19 | private var videoSurface : VideoSurface; 20 | private var _hls : HLS; 21 | 22 | public function HLSDisplayObjectTrait(hls : HLS, videoSurface : DisplayObject, mediaWidth : int = 0, mediaHeight : int = 0) { 23 | CONFIG::LOGGING { 24 | Log.debug("HLSDisplayObjectTrait()"); 25 | } 26 | _hls = hls; 27 | super(videoSurface, mediaWidth, mediaHeight); 28 | this.videoSurface = videoSurface as VideoSurface; 29 | 30 | if (this.videoSurface is VideoSurface) 31 | this.videoSurface.addEventListener(Event.ADDED_TO_STAGE, onStage); 32 | } 33 | 34 | override public function dispose() : void { 35 | CONFIG::LOGGING { 36 | Log.debug("HLSDisplayObjectTrait:dispose"); 37 | } 38 | videoSurface.removeEventListener(Event.ENTER_FRAME, onFrame); 39 | super.dispose(); 40 | } 41 | 42 | private function onStage(event : Event) : void { 43 | _hls.stage = event.target.stage as Stage; 44 | videoSurface.removeEventListener(Event.ADDED_TO_STAGE, onStage); 45 | videoSurface.addEventListener(Event.ENTER_FRAME, onFrame); 46 | } 47 | 48 | private function onFrame(event : Event) : void { 49 | var newWidth : int = videoSurface.videoWidth; 50 | var newHeight : int = videoSurface.videoHeight; 51 | if (newWidth != 0 && newHeight != 0 && (newWidth != mediaWidth || newHeight != mediaHeight)) { 52 | // If there is no layout, set as no scale. 53 | if (videoSurface.width == 0 && videoSurface.height == 0) { 54 | videoSurface.width = newWidth; 55 | videoSurface.height = newHeight; 56 | } 57 | CONFIG::LOGGING { 58 | Log.info("HLSDisplayObjectTrait:setMediaSize(" + newWidth + "," + newHeight + ")"); 59 | } 60 | setMediaSize(newWidth, newHeight); 61 | } 62 | // videoSurface.removeEventListener(Event.ENTER_FRAME, onFrame); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSDynamicStreamTrait.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.traits { 5 | import org.mangui.hls.HLS; 6 | import org.mangui.hls.event.HLSEvent; 7 | import org.osmf.traits.DynamicStreamTrait; 8 | import org.osmf.utils.OSMFStrings; 9 | 10 | CONFIG::LOGGING { 11 | import org.mangui.hls.utils.Log; 12 | } 13 | 14 | public class HLSDynamicStreamTrait extends DynamicStreamTrait { 15 | private var _hls : HLS; 16 | 17 | public function HLSDynamicStreamTrait(hls : HLS) { 18 | CONFIG::LOGGING { 19 | Log.debug("HLSDynamicStreamTrait()"); 20 | } 21 | _hls = hls; 22 | _hls.addEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler); 23 | super(true, _hls.startLevel, hls.levels.length); 24 | } 25 | 26 | override public function dispose() : void { 27 | CONFIG::LOGGING { 28 | Log.debug("HLSDynamicStreamTrait:dispose"); 29 | } 30 | _hls.removeEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler); 31 | super.dispose(); 32 | } 33 | 34 | override public function getBitrateForIndex(index : int) : Number { 35 | if (index > numDynamicStreams - 1 || index < 0) { 36 | throw new RangeError(OSMFStrings.getString(OSMFStrings.STREAMSWITCH_INVALID_INDEX)); 37 | } 38 | var bitrate : Number = _hls.levels[index].bitrate / 1000; 39 | CONFIG::LOGGING { 40 | Log.debug("HLSDynamicStreamTrait:getBitrateForIndex(" + index + ")=" + bitrate); 41 | } 42 | return bitrate; 43 | } 44 | 45 | override public function switchTo(index : int) : void { 46 | CONFIG::LOGGING { 47 | Log.debug("HLSDynamicStreamTrait:switchTo(" + index + ")/max:" + maxAllowedIndex); 48 | } 49 | if (index < 0 || index > maxAllowedIndex) { 50 | throw new RangeError(OSMFStrings.getString(OSMFStrings.STREAMSWITCH_INVALID_INDEX)); 51 | } 52 | autoSwitch = false; 53 | if (!switching) { 54 | setSwitching(true, index); 55 | } 56 | } 57 | 58 | override protected function autoSwitchChangeStart(value : Boolean) : void { 59 | CONFIG::LOGGING { 60 | Log.debug("HLSDynamicStreamTrait:autoSwitchChangeStart:" + value); 61 | } 62 | if (value == true && _hls.autoLevel == false) { 63 | _hls.nextLevel = -1; 64 | } 65 | } 66 | 67 | override protected function switchingChangeStart(newSwitching : Boolean, index : int) : void { 68 | CONFIG::LOGGING { 69 | Log.debug("HLSDynamicStreamTrait:switchingChangeStart(newSwitching/index):" + newSwitching + "/" + index); 70 | } 71 | if (newSwitching) { 72 | _hls.currentLevel = index; 73 | } 74 | } 75 | 76 | /** Update playback position/duration **/ 77 | private function _levelSwitchHandler(event : HLSEvent) : void { 78 | var newLevel : int = event.level; 79 | CONFIG::LOGGING { 80 | Log.debug("HLSDynamicStreamTrait:_qualitySwitchHandler:" + newLevel); 81 | } 82 | setCurrentIndex(newLevel); 83 | setSwitching(false, newLevel); 84 | }; 85 | } 86 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSMediaTraitType.as: -------------------------------------------------------------------------------- 1 | package org.mangui.osmf.plugins.traits 2 | { 3 | public final class HLSMediaTraitType 4 | { 5 | public static const CLOSED_CAPTIONS:String = "hlsClosedCaptions"; 6 | } 7 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSNetStreamLoadTrait.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.traits { 5 | import org.mangui.hls.HLS; 6 | import org.mangui.hls.event.HLSEvent; 7 | import org.osmf.media.MediaResourceBase; 8 | import org.osmf.net.NetStreamLoadTrait; 9 | import org.osmf.traits.LoaderBase; 10 | 11 | CONFIG::LOGGING { 12 | import org.mangui.hls.utils.Log; 13 | } 14 | 15 | public class HLSNetStreamLoadTrait extends NetStreamLoadTrait { 16 | private var _hls : HLS; 17 | private var _timeLoaded : Number; 18 | private var _timeTotal : Number; 19 | 20 | public function HLSNetStreamLoadTrait(hls : HLS, duration : Number, loader : LoaderBase, resource : MediaResourceBase) { 21 | CONFIG::LOGGING { 22 | Log.debug("HLSNetStreamLoadTrait()"); 23 | } 24 | super(loader, resource); 25 | _hls = hls; 26 | _timeLoaded = 0; 27 | _timeTotal = duration; 28 | super.netStream = _hls.stream; 29 | _hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler); 30 | } 31 | 32 | override public function dispose() : void { 33 | CONFIG::LOGGING { 34 | Log.debug("HLSNetStreamLoadTrait:dispose"); 35 | } 36 | _hls.removeEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler); 37 | super.dispose(); 38 | } 39 | 40 | override public function get bytesLoaded() : Number { 41 | return _timeLoaded; 42 | } 43 | 44 | override public function get bytesTotal() : Number { 45 | return _timeTotal; 46 | } 47 | 48 | public function get hls() : HLS { 49 | return _hls; 50 | } 51 | 52 | /** **/ 53 | private function _mediaTimeHandler(event : HLSEvent) : void { 54 | var timeTotal : Number = Math.round(10 * event.mediatime.duration) / 10; 55 | var timeLoaded : Number = Math.max(0,Math.round(10 * (event.mediatime.position + event.mediatime.buffer)) / 10); 56 | 57 | if (_timeTotal != timeTotal) { 58 | if (timeTotal < _timeLoaded || timeTotal < 0) { 59 | timeTotal = NaN; 60 | } 61 | _timeTotal = timeTotal; 62 | setBytesTotal(timeTotal); 63 | } 64 | 65 | if (_timeLoaded != timeLoaded && timeLoaded <= timeTotal) { 66 | _timeLoaded = timeLoaded; 67 | setBytesLoaded(timeLoaded); 68 | } 69 | }; 70 | } 71 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSPlayTrait.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.traits { 5 | import org.mangui.hls.HLS; 6 | import org.mangui.hls.constant.HLSPlayStates; 7 | import org.mangui.hls.event.HLSEvent; 8 | import org.osmf.traits.PlayState; 9 | import org.osmf.traits.PlayTrait; 10 | 11 | CONFIG::LOGGING { 12 | import org.mangui.hls.utils.Log; 13 | } 14 | 15 | public class HLSPlayTrait extends PlayTrait { 16 | private var _hls : HLS; 17 | private var streamStarted : Boolean = false; 18 | 19 | public function HLSPlayTrait(hls : HLS) { 20 | CONFIG::LOGGING { 21 | Log.debug("HLSPlayTrait()"); 22 | } 23 | super(); 24 | _hls = hls; 25 | _hls.addEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler); 26 | _hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete); 27 | } 28 | 29 | override public function dispose() : void { 30 | CONFIG::LOGGING { 31 | Log.debug("HLSPlayTrait:dispose"); 32 | } 33 | _hls.removeEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler); 34 | _hls.removeEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete); 35 | super.dispose(); 36 | } 37 | 38 | override protected function playStateChangeStart(newPlayState:String):void { 39 | CONFIG::LOGGING { 40 | Log.info("HLSPlayTrait:playStateChangeStart:" + newPlayState); 41 | } 42 | switch (newPlayState) { 43 | case PlayState.PLAYING: 44 | if (!streamStarted) { 45 | _hls.stream.play(); 46 | streamStarted = true; 47 | } 48 | else { 49 | _hls.stream.resume(); 50 | } 51 | break; 52 | case PlayState.PAUSED: 53 | _hls.stream.pause(); 54 | break; 55 | case PlayState.STOPPED: 56 | streamStarted = false; 57 | _hls.stream.close(); 58 | break; 59 | } 60 | } 61 | 62 | /** state changed handler **/ 63 | private function _stateChangedHandler(event:HLSEvent):void { 64 | switch (event.state) { 65 | case HLSPlayStates.PLAYING: 66 | CONFIG::LOGGING { 67 | Log.debug("HLSPlayTrait:_stateChangedHandler:setBuffering(true)"); 68 | } 69 | if (!streamStarted) { 70 | streamStarted = true; 71 | play(); 72 | } 73 | default: 74 | } 75 | } 76 | 77 | /** playback complete handler **/ 78 | private function _playbackComplete(event : HLSEvent) : void { 79 | stop(); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSSeekTrait.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.traits { 5 | import org.mangui.hls.HLS; 6 | import org.mangui.hls.event.HLSEvent; 7 | import org.mangui.hls.constant.HLSSeekStates; 8 | import org.osmf.traits.SeekTrait; 9 | import org.osmf.traits.TimeTrait; 10 | 11 | CONFIG::LOGGING { 12 | import org.mangui.hls.utils.Log; 13 | } 14 | 15 | public class HLSSeekTrait extends SeekTrait { 16 | private var _hls : HLS; 17 | 18 | public function HLSSeekTrait(hls : HLS, timeTrait : TimeTrait) { 19 | CONFIG::LOGGING { 20 | Log.debug("HLSSeekTrait()"); 21 | } 22 | super(timeTrait); 23 | _hls = hls; 24 | _hls.addEventListener(HLSEvent.SEEK_STATE, _stateChangedHandler); 25 | } 26 | 27 | override public function dispose() : void { 28 | CONFIG::LOGGING { 29 | Log.debug("HLSSeekTrait:dispose"); 30 | } 31 | _hls.removeEventListener(HLSEvent.SEEK_STATE, _stateChangedHandler); 32 | super.dispose(); 33 | } 34 | 35 | /** 36 | * @private 37 | * Communicates a seeking change to the media through the NetStream. 38 | * @param newSeeking New seeking value. 39 | * @param time Time to seek to, in seconds. 40 | */ 41 | override protected function seekingChangeStart(newSeeking : Boolean, time : Number) : void { 42 | if (newSeeking) { 43 | CONFIG::LOGGING { 44 | Log.info("HLSSeekTrait:seekingChangeStart(newSeeking/time):(" + newSeeking + "/" + time + ")"); 45 | } 46 | _hls.stream.seek(time); 47 | } 48 | super.seekingChangeStart(newSeeking, time); 49 | } 50 | 51 | /** state changed handler **/ 52 | private function _stateChangedHandler(event : HLSEvent) : void { 53 | if (seeking && event.state != HLSSeekStates.SEEKING) { 54 | CONFIG::LOGGING { 55 | Log.debug("HLSSeekTrait:setSeeking(false);"); 56 | } 57 | setSeeking(false, timeTrait.currentTime); 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/traits/HLSTimeTrait.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.traits { 5 | import org.mangui.hls.HLS; 6 | import org.mangui.hls.constant.HLSTypes; 7 | import org.mangui.hls.event.HLSEvent; 8 | import org.osmf.traits.TimeTrait; 9 | import org.osmf.events.TimeEvent; 10 | 11 | CONFIG::LOGGING { 12 | import org.mangui.hls.utils.Log; 13 | } 14 | 15 | public class HLSTimeTrait extends TimeTrait { 16 | private var _hls : HLS; 17 | 18 | public function HLSTimeTrait(hls : HLS, duration : Number = 0) { 19 | CONFIG::LOGGING { 20 | Log.debug("HLSTimeTrait()"); 21 | } 22 | super(duration); 23 | setCurrentTime(0); 24 | _hls = hls; 25 | _hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler); 26 | _hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete); 27 | } 28 | 29 | override public function dispose() : void { 30 | CONFIG::LOGGING { 31 | Log.debug("HLSTimeTrait:dispose"); 32 | } 33 | _hls.removeEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler); 34 | _hls.removeEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete); 35 | super.dispose(); 36 | } 37 | 38 | override protected function signalComplete():void 39 | { 40 | // live streams shouldn't end based on TimeTrait 41 | if (_hls.type !== HLSTypes.LIVE) 42 | { 43 | dispatchEvent(new TimeEvent(TimeEvent.COMPLETE)); 44 | } 45 | } 46 | 47 | /** Update playback position/duration **/ 48 | private function _mediaTimeHandler(event : HLSEvent) : void { 49 | var newDuration : Number = event.mediatime.duration; 50 | var newPosition : Number = Math.max(0, event.mediatime.position); 51 | setDuration(newDuration); 52 | setCurrentTime(newPosition); 53 | }; 54 | 55 | /** playback complete handler **/ 56 | private function _playbackComplete(event : HLSEvent) : void { 57 | signalComplete(); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /flashls-dev/src/org/mangui/osmf/plugins/utils/ErrorManager.as: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 | package org.mangui.osmf.plugins.utils { 5 | import org.mangui.hls.event.HLSError; 6 | import org.mangui.hls.event.HLSEvent; 7 | import org.osmf.events.MediaErrorCodes; 8 | 9 | public class ErrorManager { 10 | 11 | public static function getMediaErrorCode(event : HLSEvent) : int { 12 | var errorCode : int = MediaErrorCodes.NETSTREAM_PLAY_FAILED; 13 | if (event && event.error) { 14 | switch (event.error.code) { 15 | case HLSError.FRAGMENT_LOADING_ERROR: 16 | case HLSError.KEY_LOADING_ERROR: 17 | case HLSError.MANIFEST_LOADING_IO_ERROR: 18 | errorCode = MediaErrorCodes.IO_ERROR; 19 | break; 20 | case HLSError.FRAGMENT_LOADING_CROSSDOMAIN_ERROR: 21 | case HLSError.KEY_LOADING_CROSSDOMAIN_ERROR: 22 | case HLSError.MANIFEST_LOADING_CROSSDOMAIN_ERROR: 23 | errorCode = MediaErrorCodes.SECURITY_ERROR 24 | break; 25 | case org.mangui.hls.event.HLSError.FRAGMENT_PARSING_ERROR: 26 | case org.mangui.hls.event.HLSError.KEY_PARSING_ERROR: 27 | case org.mangui.hls.event.HLSError.MANIFEST_PARSING_ERROR: 28 | errorCode = MediaErrorCodes.NETSTREAM_FILE_STRUCTURE_INVALID; 29 | break; 30 | case org.mangui.hls.event.HLSError.TAG_APPENDING_ERROR: 31 | errorCode = MediaErrorCodes.ARGUMENT_ERROR; 32 | break; 33 | } 34 | } 35 | return errorCode; 36 | }; 37 | 38 | public static function getMediaErrorMessage(event : HLSEvent) : String { 39 | return (event && event.error) ? event.error.msg : "Unknown error"; 40 | }; 41 | }; 42 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ios-plat/m3u8player.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios-plat/m3u8player.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios-plat/m3u8player.xcodeproj/project.xcworkspace/xcuserdata/dzy.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/ios-plat/m3u8player.xcodeproj/project.xcworkspace/xcuserdata/dzy.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ios-plat/m3u8player.xcodeproj/xcuserdata/dzy.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /ios-plat/m3u8player.xcodeproj/xcuserdata/dzy.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | m3u8player.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 401ABFFF20D0F46500D305A3 16 | 17 | primary 18 | 19 | 20 | 401AC01720D0F48900D305A3 21 | 22 | primary 23 | 24 | 25 | 401AC02220D0F48900D305A3 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ios-plat/m3u8player/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // m3u8player 4 | // 5 | // Created by PPeasy on 2018/6/13. 6 | // Copyright © 2018年 PPeasy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ios-plat/m3u8player/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // m3u8player 4 | // 5 | // Created by PPeasy on 2018/6/13. 6 | // Copyright © 2018年 PPeasy. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ios-plat/m3u8player/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /ios-plat/m3u8player/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ios-plat/m3u8player/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ios-plat/m3u8player/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ios-plat/m3u8player/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ios-plat/m3u8player/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // m3u8player 4 | // 5 | // Created by PPeasy on 2018/6/13. 6 | // Copyright © 2018年 PPeasy. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ViewController : UIViewController 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ios-plat/m3u8player/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // m3u8player 4 | // 5 | // Created by PPeasy on 2018/6/13. 6 | // Copyright © 2018年 PPeasy. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; 20 | WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; 21 | //webView.allowsInlineMediaPlayback = YES; 22 | //[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://101.201.104.27/m3u8/"]]]; 23 | [webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]]]; 24 | [self.view addSubview:webView]; 25 | 26 | } 27 | 28 | 29 | - (void)didReceiveMemoryWarning { 30 | [super didReceiveMemoryWarning]; 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ios-plat/m3u8player/libppeasy.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/ios-plat/m3u8player/libppeasy.a -------------------------------------------------------------------------------- /ios-plat/m3u8player/main.mm: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // m3u8player 4 | // 5 | // Created by PPeasy on 2018/6/13. 6 | // Copyright © 2018年 PPeasy. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | void ppeasy_init_plus(); 12 | int main(int argc, char * argv[]) { 13 | ppeasy_init_plus(); 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ios-plat/m3u8playerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ios-plat/m3u8playerTests/m3u8playerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // m3u8playerTests.m 3 | // m3u8playerTests 4 | // 5 | // Created by dzy on 2018/6/13. 6 | // Copyright © 2018年 dzy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface m3u8playerTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation m3u8playerTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ios-plat/m3u8playerUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ios-plat/m3u8playerUITests/m3u8playerUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // m3u8playerUITests.m 3 | // m3u8playerUITests 4 | // 5 | // Created by dzy on 2018/6/13. 6 | // Copyright © 2018年 dzy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface m3u8playerUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation m3u8playerUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /nginx-rtmp/FAQ nginx-win version.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/FAQ nginx-win version.txt -------------------------------------------------------------------------------- /nginx-rtmp/Readme nginx-win version.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/Readme nginx-win version.txt -------------------------------------------------------------------------------- /nginx-rtmp/Tweak-Optimize tcpip parameters for nginx connections.reg: -------------------------------------------------------------------------------- 1 | REGEDIT4 2 | 3 | [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters] 4 | "TcpWindowSize"=dword:0000faf0 5 | "MaxUserPort"=dword:0000F000 6 | "TcpTimedWaitDelay"=dword:0000001e 7 | "MaxFreeTWTcbs"=dword:000003E8 8 | "MaxHashTableSize"=dword:0000800 9 | "MaxFreeTcbs"=dword:0000800 10 | "TcpNumConnections"=dword:00fffffe 11 | 12 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/EBLB/iworkcomproto.lua: -------------------------------------------------------------------------------- 1 | -- Inter Worker Communication Protocol, designed for nginx for Windows but works for any OS 2 | -- 3-3-2015 v0.3 beta http://nginx-win.ecsds.eu/ 3 | -- 0.1: initial design 4 | -- 0.2: public release 5 | -- 0.3: added lock, prevent re-entry while processing message 6 | 7 | -- set only once, global vars, 8 workers * 5 seconds = +-40 second for all workers to handle a message 8 | if not iwcp_delay then 9 | -- worker wake up every 5 seconds 10 | iwcp_delay = 5 11 | -- expire messages after 60 seconds 12 | iwcp_expire = 60 13 | iwcp_debug = nil -- or 1 to enable 14 | iwcp_show = 1 15 | math.randomseed(os.time()) 16 | local unused = math.random(1000,9999) 17 | end 18 | -- local to worker 19 | local handler 20 | local worker_pid = tostring(ngx.worker.pid()) 21 | local upstream = require "ngx.upstream" 22 | local log = ngx.log 23 | local ERR = ngx.ERR 24 | local NOTICE = ngx.NOTICE 25 | local INFO = ngx.INFO 26 | local WARN = ngx.WARN 27 | local DEBUG = ngx.DEBUG 28 | local Query = ngx.shared.iworkcomproto 29 | local QResult, wmsg, keylock 30 | local tvar1, keys, key 31 | local from, to, err, i 32 | local iwcp_one, iwcp_two, iwcp_tree 33 | 34 | handler = function (premature) 35 | if iwcp_debug then ngx.log(ngx.ERR, "timer activation for worker: "..worker_pid) end 36 | 37 | keys = Query:get_keys(0) 38 | for _,key in pairs(keys) do 39 | -- peer message handling begin 40 | from, to, err = ngx.re.find(key, "IWCP_MSG_P", "i") 41 | if from then 42 | QResult = Query:get(key) 43 | tvar1 = "#"..worker_pid.."#" 44 | from, to, err = ngx.re.find(QResult, tvar1, "i") -- is this worker PID in here? 45 | -- if not true we have a message to deal with, add PID to msg when finished processing 46 | if not from then -- and not (keylock == key) then 47 | -- keylock = key -- if processing takes a while make sure we don't process same msg(key) before finishing 48 | -- do we need to prevent re-entry or do we need to advice to pass long running jobs to a co-socket? 49 | if iwcp_show then ngx.log(ngx.ERR, "message for worker: "..worker_pid..", key: "..key..", msg: "..QResult) end 50 | from, to, err = ngx.re.find(QResult, "!", "i") 51 | i = string.sub(QResult, from+1, string.len(QResult)) -- get message parameters 52 | iwcp_one, iwcp_two, iwcp_tree = i:match("([^,]+),([^,]+),([^,]+)") -- split up parameters 53 | -- all commands and values are in vars, run commands in this worker 54 | from, to, err = ngx.re.find(key, "IWCP_MSG_PD_", "i") -- peer down 55 | if from then 56 | ok, err = upstream.set_peer_down(iwcp_one, false, tonumber(iwcp_two), true) 57 | end 58 | from, to, err = ngx.re.find(key, "IWCP_MSG_PU_", "i") -- peer up 59 | if from then 60 | ok, err = upstream.set_peer_down(iwcp_one, false, tonumber(iwcp_two), false) 61 | end 62 | from, to, err = ngx.re.find(key, "IWCP_MSG_PI_", "i") -- peer change addr(ip:port) 63 | if from then 64 | ok, err = upstream.set_peer_addr(iwcp_one, false, tonumber(iwcp_two), iwcp_tree) 65 | end 66 | -- log results 67 | if iwcp_show then ngx.log(ngx.ERR, "result: "..tostring(ok)..", for worker: "..worker_pid..", err: "..tostring(err)..", key: "..key) end 68 | -- update key 69 | QResult = "#"..worker_pid..QResult 70 | Query:replace(key,QResult,iwcp_expire) 71 | -- keylock = nil 72 | end 73 | end 74 | -- peer message handling end 75 | end 76 | 77 | if premature then 78 | return 79 | end 80 | ok, err = ngx.timer.at(iwcp_delay, handler) 81 | if not ok then 82 | if iwcp_debug then ngx.log(ngx.ERR, "failed to create the timer: ", err) end 83 | return 84 | end 85 | end 86 | 87 | ok, err = ngx.timer.at(iwcp_delay, handler) 88 | if not ok then 89 | if iwcp_debug then ngx.log(ngx.ERR, "failed to create the timer: ", err) end 90 | return 91 | end 92 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/EBLB/upstream_EBLB_with_IWCP.txt: -------------------------------------------------------------------------------- 1 | 2-3-2015: added Inter Worker Communication Protocol to support multiple workers (IWCP) 2 | 28-2-2015: updated source 3 | 27-2-2015: It works! Commercially sponsored by nginx for Windows, coding by vozlt 4 | 5 | EBLB (Elastic Backend Load Balancer) 6 | 7 | Upstream status and control, a mod for ngx_http_lua_upstream_module.c 8 | https://github.com/openresty/lua-upstream-nginx-module 9 | 10 | Files: 11 | upstreamcontrol.lua Lua code to change upstream peer runtime values 12 | upstreamstatus.lua Lua code to view upstream status (GUI) 13 | upstream_candc.conf nginx config for testing and serve as an example 14 | iworkcomproto.lua Inter Worker Communication Protocol 15 | nb. set 'iwcp_debug = nil' to log only iwcp messages/results 16 | ----- 17 | Place .conf/.lua files in nginx/conf 18 | 19 | 20 | run example : nginx -c ./conf/upstream_candc.conf 21 | http view : http://127.0.0.1/upstreamstatus 22 | curl : curl -i "http://127.0.0.1/upstreamcontrol?down=true&peer=0&stream=luaupstfoo" 23 | curl : curl -i "http://127.0.0.1/upstreamcontrol?addr=192.168.169.9&peer=0&stream=luaupstfoo" 24 | curl : curl -i "http://127.0.0.1/upstreamcontrol?addr=192.168.169.2:85&peer=0&stream=luaupstfoo" 25 | NB. either use allow/deny for management IP addresses or auth_basic to prevent someone else from 26 | changing your upstreams. 27 | 28 | 29 | Issues: 30 | 1. To change the port add it to the addr field, don't use total value larger then set in your 31 | nginx.conf file! (always use IP address:port in your upstreams) 32 | 2. Ipv6 not tested 33 | see also https://groups.google.com/forum/#!topic/openresty-en/wt_9m7GvROg (links to c source) 34 | 35 | 36 | Use cases: 37 | 1. Create a large number of upstream servers in one upstream block, set 75% as down and 38 | switch numbers online as needed. 39 | 2. Move large attacks on a upstream to a part of the pool configured to deal with this. 40 | 3. Allow script access (curl) when a server is going down mark it down via it's shutdown script. 41 | 4. Take backends down while maintenance is being done and back up with a single click 42 | or script. 43 | 5. Scale the number of backends (down/up) based on external monitoring. 44 | 6. Swap servers between upstreams by changing their ip address. 45 | 46 | 47 | Why not via DNS resolving? 48 | DNS can be too slow, not under your control, not allowing changes, remote DNS can go offline, 49 | not fast enough when redirecting attacks, etc... 50 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/EBLB/upstream_candc.conf: -------------------------------------------------------------------------------- 1 | 2 | worker_processes 4; 3 | #worker_processes 1; # more then 1 worker is only supported with IWCP (iworkcomproto.lua) 4 | error_log logs/error.log; 5 | #error_log logs/error.log debug; 6 | 7 | events { 8 | worker_connections 8192; 9 | } 10 | 11 | http { 12 | include mime.types; 13 | default_type application/octet-stream; 14 | log_format main '[$time_local] $remote_addr:$remote_port - $remote_user $scheme "$request" ' 15 | '$status $body_bytes_sent "$http_referer" ' 16 | '"$http_user_agent" "$http_x_forwarded_for" $upstream_cache_status'; 17 | access_log logs/access.log main; 18 | sendfile off; 19 | #tcp_nopush on; 20 | server_names_hash_bucket_size 128; 21 | gzip on; 22 | 23 | # 1m = +-10.000 messages 24 | lua_shared_dict iworkcomproto 1m; 25 | 26 | init_worker_by_lua_file conf/iworkcomproto.lua; 27 | 28 | upstream luaupstfoo { 29 | server 192.168.169.2:80 weight=1 fail_timeout=5; 30 | server 192.168.169.17:80 weight=1 fail_timeout=5; 31 | server 192.168.169.26:80 weight=1 fail_timeout=5 down; 32 | least_conn; 33 | } 34 | upstream luaupstbar { 35 | server 192.168.169.3:80; 36 | } 37 | 38 | server { 39 | listen 80; 40 | server_name localhost; 41 | 42 | location = /upstreamcontrol { 43 | default_type text/html; 44 | content_by_lua_file conf/upstreamcontrol.lua; 45 | } 46 | 47 | # curl -i http://127.0.0.1/upstreamstatus 48 | location = /upstreamstatus { 49 | default_type text/html; 50 | content_by_lua_file conf/upstreamstatus.lua; 51 | } 52 | 53 | # curl -i "http://127.0.0.1/pt" 54 | location /pt { 55 | include c:/nginx/conf/proxy.conf; 56 | keepalive_requests 500; 57 | proxy_http_version 1.1; 58 | proxy_ignore_client_abort on; 59 | proxy_pass http://luaupstfoo; 60 | } 61 | 62 | } # server end 63 | 64 | } 65 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/EBLB/upstreamcontrol.lua: -------------------------------------------------------------------------------- 1 | -- 0.3 changes: prevent IWCP usage when IWCP is not loaded (1 worker) 2 | 3 | local args = ngx.req.get_uri_args() 4 | local i_stream, i_peer, i_name, i_server, i_down, i_gui, ok, err, cdone, i_vdown, i_temp, i_addr_ip, addr_port 5 | i_gui = args["gui"] 6 | i_stream = args["stream"] -- upstream name 7 | i_peer = args["peer"] -- number 8 | i_name = args["name"] -- resolved 9 | i_server = args["server"] -- from conf 10 | i_addr_ip = args["addr"] -- from runtime current worker only 11 | i_down = args["down"] 12 | i_vdown = args["vdown"] 13 | local worker_pid = tostring(ngx.worker.pid()) 14 | local Query = ngx.shared.iworkcomproto 15 | local iwcp_t = os.time() -- create unique message keys 16 | local iwcp_r = tostring(math.random(1000,9999)) -- create unique message keys part2 17 | -- 18 | if i_vdown then i_down = i_vdown end 19 | if i_down == "1" then i_down = "true" end 20 | if i_down == "0" then i_down = "false" end 21 | if i_name then i_temp = ngx.re.gsub(i_name, "%3A", ":") end 22 | if i_name then i_name = i_temp end 23 | if i_server then i_temp = ngx.re.gsub(i_server, "%3A", ":") end 24 | if i_server then i_server = i_temp end 25 | if i_addr_ip then i_temp = ngx.re.gsub(i_addr_ip, "%3A", ":") end 26 | if i_addr_ip then i_addr_ip = i_temp end 27 | cdone = 1 28 | -- 29 | 30 | if i_down and cdone then 31 | local upstream = require "ngx.upstream" 32 | if i_down == "true" then 33 | ok, err = upstream.set_peer_down(i_stream, false, tonumber(i_peer), true) 34 | if ok and iwcp_expire then 35 | Query:set("IWCP_MSG_PD_"..iwcp_t..iwcp_r,"#"..worker_pid.."#!"..tostring(i_stream)..","..tonumber(i_peer)..",0",iwcp_expire) 36 | end 37 | ngx.print("down ",ok," ",err,"\n") 38 | else 39 | ok, err = upstream.set_peer_down(i_stream, false, tonumber(i_peer), false) 40 | if ok and iwcp_expire then 41 | Query:set("IWCP_MSG_PU_"..iwcp_t..iwcp_r,"#"..worker_pid.."#!"..tostring(i_stream)..","..tonumber(i_peer)..",1",iwcp_expire) 42 | end 43 | ngx.print("up ",ok," ",err,"\n") 44 | end 45 | if not i_gui then return end 46 | cdone = 0 47 | end 48 | 49 | if i_addr_ip and cdone then 50 | local upstream = require "ngx.upstream" 51 | ok, err = upstream.set_peer_addr(i_stream, false, tonumber(i_peer), i_addr_ip) 52 | if ok and iwcp_expire then 53 | Query:set("IWCP_MSG_PI_"..iwcp_t..iwcp_r,"#"..worker_pid.."#!"..tostring(i_stream)..","..tonumber(i_peer)..","..i_addr_ip,iwcp_expire) 54 | end 55 | ngx.print("changed ",ok," ",err,"\n") 56 | if not i_gui then return end 57 | cdone = 0 58 | end 59 | 60 | if cdone == 1 then ngx.print("not yet implemented !\n") end 61 | if not i_gui then return end 62 | 63 | ngx.print("\n") 64 | return 65 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/fastcgi.conf: -------------------------------------------------------------------------------- 1 | 2 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 3 | fastcgi_param QUERY_STRING $query_string; 4 | fastcgi_param REQUEST_METHOD $request_method; 5 | fastcgi_param CONTENT_TYPE $content_type; 6 | fastcgi_param CONTENT_LENGTH $content_length; 7 | 8 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 9 | fastcgi_param REQUEST_URI $request_uri; 10 | fastcgi_param DOCUMENT_URI $document_uri; 11 | fastcgi_param DOCUMENT_ROOT $document_root; 12 | fastcgi_param SERVER_PROTOCOL $server_protocol; 13 | fastcgi_param HTTPS $https if_not_empty; 14 | 15 | fastcgi_param GATEWAY_INTERFACE CGI/1.1; 16 | fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; 17 | 18 | fastcgi_param REMOTE_ADDR $remote_addr; 19 | fastcgi_param REMOTE_PORT $remote_port; 20 | fastcgi_param SERVER_ADDR $server_addr; 21 | fastcgi_param SERVER_PORT $server_port; 22 | fastcgi_param SERVER_NAME $server_name; 23 | 24 | # PHP only, required if PHP was built with --enable-force-cgi-redirect 25 | fastcgi_param REDIRECT_STATUS 200; 26 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/fastcgi_params: -------------------------------------------------------------------------------- 1 | 2 | fastcgi_param QUERY_STRING $query_string; 3 | fastcgi_param REQUEST_METHOD $request_method; 4 | fastcgi_param CONTENT_TYPE $content_type; 5 | fastcgi_param CONTENT_LENGTH $content_length; 6 | 7 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 8 | fastcgi_param REQUEST_URI $request_uri; 9 | fastcgi_param DOCUMENT_URI $document_uri; 10 | fastcgi_param DOCUMENT_ROOT $document_root; 11 | fastcgi_param SERVER_PROTOCOL $server_protocol; 12 | fastcgi_param HTTPS $https if_not_empty; 13 | 14 | fastcgi_param GATEWAY_INTERFACE CGI/1.1; 15 | fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; 16 | 17 | fastcgi_param REMOTE_ADDR $remote_addr; 18 | fastcgi_param REMOTE_PORT $remote_port; 19 | fastcgi_param SERVER_ADDR $server_addr; 20 | fastcgi_param SERVER_PORT $server_port; 21 | fastcgi_param SERVER_NAME $server_name; 22 | 23 | # PHP only, required if PHP was built with --enable-force-cgi-redirect 24 | fastcgi_param REDIRECT_STATUS 200; 25 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/koi-utf: -------------------------------------------------------------------------------- 1 | 2 | # This map is not a full koi8-r <> utf8 map: it does not contain 3 | # box-drawing and some other characters. Besides this map contains 4 | # several koi8-u and Byelorussian letters which are not in koi8-r. 5 | # If you need a full and standard map, use contrib/unicode2nginx/koi-utf 6 | # map instead. 7 | 8 | charset_map koi8-r utf-8 { 9 | 10 | 80 E282AC ; # euro 11 | 12 | 95 E280A2 ; # bullet 13 | 14 | 9A C2A0 ; #   15 | 16 | 9E C2B7 ; # · 17 | 18 | A3 D191 ; # small yo 19 | A4 D194 ; # small Ukrainian ye 20 | 21 | A6 D196 ; # small Ukrainian i 22 | A7 D197 ; # small Ukrainian yi 23 | 24 | AD D291 ; # small Ukrainian soft g 25 | AE D19E ; # small Byelorussian short u 26 | 27 | B0 C2B0 ; # ° 28 | 29 | B3 D081 ; # capital YO 30 | B4 D084 ; # capital Ukrainian YE 31 | 32 | B6 D086 ; # capital Ukrainian I 33 | B7 D087 ; # capital Ukrainian YI 34 | 35 | B9 E28496 ; # numero sign 36 | 37 | BD D290 ; # capital Ukrainian soft G 38 | BE D18E ; # capital Byelorussian short U 39 | 40 | BF C2A9 ; # (C) 41 | 42 | C0 D18E ; # small yu 43 | C1 D0B0 ; # small a 44 | C2 D0B1 ; # small b 45 | C3 D186 ; # small ts 46 | C4 D0B4 ; # small d 47 | C5 D0B5 ; # small ye 48 | C6 D184 ; # small f 49 | C7 D0B3 ; # small g 50 | C8 D185 ; # small kh 51 | C9 D0B8 ; # small i 52 | CA D0B9 ; # small j 53 | CB D0BA ; # small k 54 | CC D0BB ; # small l 55 | CD D0BC ; # small m 56 | CE D0BD ; # small n 57 | CF D0BE ; # small o 58 | 59 | D0 D0BF ; # small p 60 | D1 D18F ; # small ya 61 | D2 D180 ; # small r 62 | D3 D181 ; # small s 63 | D4 D182 ; # small t 64 | D5 D183 ; # small u 65 | D6 D0B6 ; # small zh 66 | D7 D0B2 ; # small v 67 | D8 D18C ; # small soft sign 68 | D9 D18B ; # small y 69 | DA D0B7 ; # small z 70 | DB D188 ; # small sh 71 | DC D18D ; # small e 72 | DD D189 ; # small shch 73 | DE D187 ; # small ch 74 | DF D18A ; # small hard sign 75 | 76 | E0 D0AE ; # capital YU 77 | E1 D090 ; # capital A 78 | E2 D091 ; # capital B 79 | E3 D0A6 ; # capital TS 80 | E4 D094 ; # capital D 81 | E5 D095 ; # capital YE 82 | E6 D0A4 ; # capital F 83 | E7 D093 ; # capital G 84 | E8 D0A5 ; # capital KH 85 | E9 D098 ; # capital I 86 | EA D099 ; # capital J 87 | EB D09A ; # capital K 88 | EC D09B ; # capital L 89 | ED D09C ; # capital M 90 | EE D09D ; # capital N 91 | EF D09E ; # capital O 92 | 93 | F0 D09F ; # capital P 94 | F1 D0AF ; # capital YA 95 | F2 D0A0 ; # capital R 96 | F3 D0A1 ; # capital S 97 | F4 D0A2 ; # capital T 98 | F5 D0A3 ; # capital U 99 | F6 D096 ; # capital ZH 100 | F7 D092 ; # capital V 101 | F8 D0AC ; # capital soft sign 102 | F9 D0AB ; # capital Y 103 | FA D097 ; # capital Z 104 | FB D0A8 ; # capital SH 105 | FC D0AD ; # capital E 106 | FD D0A9 ; # capital SHCH 107 | FE D0A7 ; # capital CH 108 | FF D0AA ; # capital hard sign 109 | } 110 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/koi-win: -------------------------------------------------------------------------------- 1 | 2 | charset_map koi8-r windows-1251 { 3 | 4 | 80 88 ; # euro 5 | 6 | 95 95 ; # bullet 7 | 8 | 9A A0 ; #   9 | 10 | 9E B7 ; # · 11 | 12 | A3 B8 ; # small yo 13 | A4 BA ; # small Ukrainian ye 14 | 15 | A6 B3 ; # small Ukrainian i 16 | A7 BF ; # small Ukrainian yi 17 | 18 | AD B4 ; # small Ukrainian soft g 19 | AE A2 ; # small Byelorussian short u 20 | 21 | B0 B0 ; # ° 22 | 23 | B3 A8 ; # capital YO 24 | B4 AA ; # capital Ukrainian YE 25 | 26 | B6 B2 ; # capital Ukrainian I 27 | B7 AF ; # capital Ukrainian YI 28 | 29 | B9 B9 ; # numero sign 30 | 31 | BD A5 ; # capital Ukrainian soft G 32 | BE A1 ; # capital Byelorussian short U 33 | 34 | BF A9 ; # (C) 35 | 36 | C0 FE ; # small yu 37 | C1 E0 ; # small a 38 | C2 E1 ; # small b 39 | C3 F6 ; # small ts 40 | C4 E4 ; # small d 41 | C5 E5 ; # small ye 42 | C6 F4 ; # small f 43 | C7 E3 ; # small g 44 | C8 F5 ; # small kh 45 | C9 E8 ; # small i 46 | CA E9 ; # small j 47 | CB EA ; # small k 48 | CC EB ; # small l 49 | CD EC ; # small m 50 | CE ED ; # small n 51 | CF EE ; # small o 52 | 53 | D0 EF ; # small p 54 | D1 FF ; # small ya 55 | D2 F0 ; # small r 56 | D3 F1 ; # small s 57 | D4 F2 ; # small t 58 | D5 F3 ; # small u 59 | D6 E6 ; # small zh 60 | D7 E2 ; # small v 61 | D8 FC ; # small soft sign 62 | D9 FB ; # small y 63 | DA E7 ; # small z 64 | DB F8 ; # small sh 65 | DC FD ; # small e 66 | DD F9 ; # small shch 67 | DE F7 ; # small ch 68 | DF FA ; # small hard sign 69 | 70 | E0 DE ; # capital YU 71 | E1 C0 ; # capital A 72 | E2 C1 ; # capital B 73 | E3 D6 ; # capital TS 74 | E4 C4 ; # capital D 75 | E5 C5 ; # capital YE 76 | E6 D4 ; # capital F 77 | E7 C3 ; # capital G 78 | E8 D5 ; # capital KH 79 | E9 C8 ; # capital I 80 | EA C9 ; # capital J 81 | EB CA ; # capital K 82 | EC CB ; # capital L 83 | ED CC ; # capital M 84 | EE CD ; # capital N 85 | EF CE ; # capital O 86 | 87 | F0 CF ; # capital P 88 | F1 DF ; # capital YA 89 | F2 D0 ; # capital R 90 | F3 D1 ; # capital S 91 | F4 D2 ; # capital T 92 | F5 D3 ; # capital U 93 | F6 C6 ; # capital ZH 94 | F7 C2 ; # capital V 95 | F8 DC ; # capital soft sign 96 | F9 DB ; # capital Y 97 | FA C7 ; # capital Z 98 | FB D8 ; # capital SH 99 | FC DD ; # capital E 100 | FD D9 ; # capital SHCH 101 | FE D7 ; # capital CH 102 | FF DA ; # capital hard sign 103 | } 104 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/mysite.rules: -------------------------------------------------------------------------------- 1 | LearningMode; #Enables learning mode 2 | SecRulesEnabled; 3 | #SecRulesDisabled; 4 | DeniedUrl "/RequestDenied"; 5 | ## check rules 6 | CheckRule "$SQL >= 8" BLOCK; 7 | CheckRule "$RFI >= 8" BLOCK; 8 | CheckRule "$TRAVERSAL >= 4" BLOCK; 9 | CheckRule "$EVADE >= 4" BLOCK; 10 | CheckRule "$XSS >= 8" BLOCK; 11 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/nginx-org.conf: -------------------------------------------------------------------------------- 1 | 2 | #user nobody; 3 | worker_processes 1; 4 | 5 | #error_log logs/error.log; 6 | #error_log logs/error.log notice; 7 | #error_log logs/error.log info; 8 | 9 | #pid logs/nginx.pid; 10 | 11 | 12 | events { 13 | worker_connections 1024; 14 | } 15 | 16 | 17 | http { 18 | include mime.types; 19 | default_type application/octet-stream; 20 | 21 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 22 | # '$status $body_bytes_sent "$http_referer" ' 23 | # '"$http_user_agent" "$http_x_forwarded_for"'; 24 | 25 | #access_log logs/access.log main; 26 | 27 | sendfile on; 28 | #tcp_nopush on; 29 | 30 | #keepalive_timeout 0; 31 | keepalive_timeout 65; 32 | 33 | #gzip on; 34 | 35 | server { 36 | listen 80; 37 | server_name localhost; 38 | 39 | #charset koi8-r; 40 | 41 | #access_log logs/host.access.log main; 42 | 43 | location / { 44 | root html; 45 | index index.html index.htm; 46 | } 47 | 48 | #error_page 404 /404.html; 49 | 50 | # redirect server error pages to the static page /50x.html 51 | # 52 | error_page 500 502 503 504 /50x.html; 53 | location = /50x.html { 54 | root html; 55 | } 56 | 57 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 58 | # 59 | #location ~ \.php$ { 60 | # proxy_pass http://127.0.0.1; 61 | #} 62 | 63 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 64 | # 65 | #location ~ \.php$ { 66 | # root html; 67 | # fastcgi_pass 127.0.0.1:9000; 68 | # fastcgi_index index.php; 69 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 70 | # include fastcgi_params; 71 | #} 72 | 73 | # deny access to .htaccess files, if Apache's document root 74 | # concurs with nginx's one 75 | # 76 | #location ~ /\.ht { 77 | # deny all; 78 | #} 79 | } 80 | 81 | 82 | # another virtual host using mix of IP-, name-, and port-based configuration 83 | # 84 | #server { 85 | # listen 8000; 86 | # listen somename:8080; 87 | # server_name somename alias another.alias; 88 | 89 | # location / { 90 | # root html; 91 | # index index.html index.htm; 92 | # } 93 | #} 94 | 95 | 96 | # HTTPS server 97 | # 98 | #server { 99 | # listen 443 ssl; 100 | # server_name localhost; 101 | 102 | # ssl_certificate cert.pem; 103 | # ssl_certificate_key cert.key; 104 | 105 | # ssl_session_cache shared:SSL:1m; 106 | # ssl_session_timeout 5m; 107 | 108 | # ssl_ciphers HIGH:!aNULL:!MD5; 109 | # ssl_prefer_server_ciphers on; 110 | 111 | # location / { 112 | # root html; 113 | # index index.html index.htm; 114 | # } 115 | #} 116 | 117 | } 118 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/nginx-simple-WAF.conf: -------------------------------------------------------------------------------- 1 | # http://nginx-win.ecsds.eu/ 2 | # 3 | # A very simple Web Application Firewall 4 | # 5 | map $http_referer $waffableref { 6 | default 0; 7 | ~*\{.*\:\; 1; 8 | } 9 | map $http_user_agent $waffableua { 10 | default 0; 11 | ~*\{.*\:\; 1; 12 | } 13 | map $request $waffablereq { 14 | default 0; 15 | ~*cgi-bin 1; 16 | ~*editor\/ 1; 17 | ~*mysql 1; 18 | ~*vtigercrm 1; 19 | ~*webdav 1; 20 | ~*xmlrpc\.php 1; 21 | ~*\/admin\.php 1; 22 | ~*\/admin\/config\.php 1; 23 | ~*\/admin\/common\/ 1; 24 | ~*\/admin\/reports\.php 1; 25 | ~*\/administrator 1; 26 | ~*\/connector\.asp 1; 27 | ~*\/elfinder 1; 28 | ~*\/exec\/ 1; 29 | ~*\/HNAP1\/ 1; 30 | ~*\/hudson\/script 1; 31 | ~*\/include\/shell\.php 1; 32 | ~*\/invoker\/EJBInvokerServlet 1; 33 | ~*\/manager\/ht 1; 34 | ~*\/muieblackcat 1; 35 | ~*\/proxy.txt 1; 36 | ~*\/scripts\/setup 1; 37 | ~*\/session\/login\.php 1; 38 | ~*\/sprawdza\.php 1; 39 | ~*\/sqlite 1; 40 | ~*\/web-console\/ 1; 41 | ~*\/wordpress\/wp-admin\/ 1; 42 | ~*\/wp-login\.php 1; 43 | ~*\/zologize\/axa\.php 1; 44 | } 45 | map $waffablereq$waffableref$waffableua $waffable { 46 | default 0; 47 | ~1 1; 48 | } 49 | # you could break something you use yourself :) 50 | # between http {} include nginx-simple-WAF.conf; 51 | # inside location {} if ($waffable) { error_page 412 @412fart; return 412; } 52 | # or a simple { return 412; } 53 | # inside server {} after last location, location @412fart { root html; rewrite ^ /412fart.html break; } 54 | # 55 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | #user nobody; 2 | worker_processes 1; 3 | 4 | #error_log logs/error.log; 5 | #error_log logs/error.log notice; 6 | #error_log logs/error.log info; 7 | 8 | #pid logs/nginx.pid; 9 | 10 | 11 | events { 12 | worker_connections 1024; 13 | } 14 | 15 | rtmp { 16 | server { 17 | listen 1935; 18 | application hls { 19 | live on; 20 | hls on; 21 | hls_path tmp/app/; 22 | hls_fragment 5s; 23 | 24 | } 25 | } 26 | } 27 | 28 | http { 29 | include mime.types; 30 | default_type application/octet-stream; 31 | 32 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 33 | # '$status $body_bytes_sent "$http_referer" ' 34 | # '"$http_user_agent" "$http_x_forwarded_for"'; 35 | 36 | #access_log logs/access.log main; 37 | 38 | sendfile on; 39 | #tcp_nopush on; 40 | 41 | #keepalive_timeout 0; 42 | keepalive_timeout 65; 43 | 44 | #gzip on; 45 | 46 | server { 47 | listen 80; 48 | server_name localhost; 49 | 50 | #charset koi8-r; 51 | 52 | #access_log logs/host.access.log main; 53 | 54 | location / { 55 | root html; 56 | index index.html index.htm; 57 | } 58 | location /hls { 59 | types{ 60 | application/vnd.apple.mpegurl m3u8; 61 | video/mp2t ts; 62 | } 63 | alias tmp/app/; 64 | expires -1; 65 | } 66 | 67 | #error_page 404 /404.html; 68 | 69 | # redirect server error pages to the static page /50x.html 70 | # 71 | error_page 500 502 503 504 /50x.html; 72 | location = /50x.html { 73 | root html; 74 | } 75 | 76 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 77 | # 78 | #location ~ \.php$ { 79 | # proxy_pass http://127.0.0.1; 80 | #} 81 | 82 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 83 | # 84 | #location ~ \.php$ { 85 | # root html; 86 | # fastcgi_pass 127.0.0.1:9000; 87 | # fastcgi_index index.php; 88 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 89 | # include fastcgi_params; 90 | #} 91 | 92 | # deny access to .htaccess files, if Apache's document root 93 | # concurs with nginx's one 94 | # 95 | #location ~ /\.ht { 96 | # deny all; 97 | #} 98 | } 99 | 100 | 101 | # another virtual host using mix of IP-, name-, and port-based configuration 102 | # 103 | #server { 104 | # listen 8000; 105 | # listen somename:8080; 106 | # server_name somename alias another.alias; 107 | 108 | # location / { 109 | # root html; 110 | # index index.html index.htm; 111 | # } 112 | #} 113 | 114 | 115 | # HTTPS server 116 | # 117 | #server { 118 | # listen 443 ssl; 119 | # server_name localhost; 120 | 121 | # ssl_certificate cert.pem; 122 | # ssl_certificate_key cert.key; 123 | 124 | # ssl_session_cache shared:SSL:1m; 125 | # ssl_session_timeout 5m; 126 | 127 | # ssl_ciphers HIGH:!aNULL:!MD5; 128 | # ssl_prefer_server_ciphers on; 129 | 130 | # location / { 131 | # root html; 132 | # index index.html index.htm; 133 | # } 134 | #} 135 | 136 | } -------------------------------------------------------------------------------- /nginx-rtmp/conf/php-opcache-example.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | 3 | 4 | ;; php.ini ..............near/at the end: 5 | 6 | ;; http://php.net/manual/en/opcache.installation.php 7 | ;; https://github.com/zendtech/ZendOptimizerPlus 8 | ;; http://www.apachelounge.com/viewtopic.php?t=6389&postdays=0&postorder=asc&start=0 9 | ;; php 5.5.x or higher required 10 | 11 | zend_extension=php_opcache.dll 12 | 13 | [opcache] 14 | opcache.memory_consumption=256 15 | opcache.interned_strings_buffer=8 16 | opcache.max_accelerated_files=8000 17 | opcache.revalidate_freq=60 18 | opcache.fast_shutdown=1 19 | opcache.enable_cli=0 20 | opcache.enable_file_override=1 21 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/php-xcache-example.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | 3 | 4 | ;; php.ini ..............near/at the end: 5 | 6 | ;; http://xcache.lighttpd.net/ 7 | ;; http://xcache.lighttpd.net/wiki/ReleaseArchive 8 | ;; https://groups.google.com/forum/#!forum/xcache 9 | 10 | [xcache-common] 11 | extension = php_xcache.dll 12 | 13 | [xcache.admin] 14 | xcache.admin.enable_auth = On 15 | xcache.admin.user = "xuser" 16 | ; xcache.admin.pass = md5($your_password) 17 | xcache.admin.pass = "blabla" 18 | 19 | [xcache] 20 | ; select low level shm/allocator scheme implemenation 21 | xcache.shm_scheme = "mmap" 22 | ; to disable: xcache.size=0 23 | ; to enable : xcache.size=64M etc (any size > 0) and your system mmap allows 24 | xcache.size = 32M 25 | ; set to cpu count (cat /proc/cpuinfo |grep -c processor) 26 | xcache.count = 1 27 | ; just a hash hints, you can always store count(items) > slots 28 | xcache.slots = 8K 29 | ; ttl of the cache item, 0=forever 30 | xcache.ttl = 0 31 | ; interval of gc scanning expired items, 0=no scan, other values is in seconds 32 | xcache.gc_interval = 0 33 | 34 | ; same as aboves but for variable cache 35 | xcache.var_size = 4M 36 | xcache.var_count = 1 37 | xcache.var_slots = 8K 38 | xcache.var_ttl = 0 39 | xcache.var_maxttl = 0 40 | xcache.var_gc_interval = 300 41 | 42 | ; mode:0, const string specified by xcache.var_namespace 43 | ; mode:1, $_SERVER[xcache.var_namespace] 44 | ; mode:2, uid or gid (specified by xcache.var_namespace) 45 | xcache.var_namespace_mode = 0 46 | xcache.var_namespace = "" 47 | 48 | ; N/A for /dev/zero 49 | xcache.readonly_protection = Off 50 | ; for *nix, xcache.mmap_path is a file path, not directory. 51 | ; Use something like "/tmp/xcache" if you want to turn on ReadonlyProtection 52 | ; 2 group of php won't share the same /tmp/xcache 53 | ; for win32, xcache.mmap_path=anonymous map name, not file path 54 | ; xcache.mmap_path = "/dev/zero" 55 | xcache.mmap_path = "xcachemmap" 56 | 57 | ; leave it blank(disabled) or "/tmp/phpcore/" 58 | ; make sure it's writable by php (open_basedir is not checked) 59 | xcache.coredump_directory = "" 60 | ; Windows only. leave it as 0 (default) until you're told by XCache dev 61 | xcache.coredump_type = 0 62 | 63 | ; disable cache after crash 64 | xcache.disable_on_crash = Off 65 | xcache.experimental = Off 66 | 67 | ; per request settings 68 | xcache.cacher = On 69 | xcache.stat = On 70 | xcache.optimizer = On 71 | 72 | [xcache.coverager] 73 | ; per request settings 74 | ; enable coverage data collecting for xcache.coveragedump_directory and xcache_coverager_start/stop/get/clean() functions (will hurt executing performance) 75 | xcache.coverager = Off 76 | xcache.coverager_autostart = On 77 | 78 | ; ini only settings 79 | ; make sure it's readable (open_basedir is checked) by coverage viewer script 80 | ; requires xcache.coverager=On 81 | xcache.coveragedump_directory = "" 82 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/scgi_params: -------------------------------------------------------------------------------- 1 | 2 | scgi_param REQUEST_METHOD $request_method; 3 | scgi_param REQUEST_URI $request_uri; 4 | scgi_param QUERY_STRING $query_string; 5 | scgi_param CONTENT_TYPE $content_type; 6 | 7 | scgi_param DOCUMENT_URI $document_uri; 8 | scgi_param DOCUMENT_ROOT $document_root; 9 | scgi_param SCGI 1; 10 | scgi_param SERVER_PROTOCOL $server_protocol; 11 | scgi_param HTTPS $https if_not_empty; 12 | 13 | scgi_param REMOTE_ADDR $remote_addr; 14 | scgi_param REMOTE_PORT $remote_port; 15 | scgi_param SERVER_PORT $server_port; 16 | scgi_param SERVER_NAME $server_name; 17 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/uwsgi_params: -------------------------------------------------------------------------------- 1 | 2 | uwsgi_param QUERY_STRING $query_string; 3 | uwsgi_param REQUEST_METHOD $request_method; 4 | uwsgi_param CONTENT_TYPE $content_type; 5 | uwsgi_param CONTENT_LENGTH $content_length; 6 | 7 | uwsgi_param REQUEST_URI $request_uri; 8 | uwsgi_param PATH_INFO $document_uri; 9 | uwsgi_param DOCUMENT_ROOT $document_root; 10 | uwsgi_param SERVER_PROTOCOL $server_protocol; 11 | uwsgi_param HTTPS $https if_not_empty; 12 | 13 | uwsgi_param REMOTE_ADDR $remote_addr; 14 | uwsgi_param REMOTE_PORT $remote_port; 15 | uwsgi_param SERVER_PORT $server_port; 16 | uwsgi_param SERVER_NAME $server_name; 17 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/vhts/VHTS.txt: -------------------------------------------------------------------------------- 1 | nginx for Windows 2 | http://nginx-win.ecsds.eu/ 3 | 4 | 5 | nginx-module-vts (Virtual host traffic status) 6 | 7 | 8 | http { 9 | ........... 10 | vhost_traffic_status_zone shared:vhts:1m; 11 | ........... 12 | server { 13 | listen 80; 14 | ........... 15 | location /ngxvtstatus { 16 | vhost_traffic_status_display; 17 | vhost_traffic_status_display_format html; 18 | } 19 | 20 | 21 | 22 | Place vtsvalues*.js files in the root where 'location /ngxvtstatus' (or nginx root) is located, check 23 | your logfiles if you are not seeing updates in the web frontend (404, javascript files not found). 24 | Some default values are build in, the .js files overrides them when required. 25 | 26 | 27 | 28 | Adjust the values in the vtsvalues*.js files when required to your needs. 29 | 30 | 31 | NB. either use allow/deny for management IP addresses or auth_basic to prevent someone else from 32 | viewing the status. 33 | 34 | 35 | Enjoy! 36 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/vhts/vtsvalues-eop.js: -------------------------------------------------------------------------------- 1 | // vts values EndOfPage, change properties after page has been loaded 2 | 3 | function updatetimedate() { 4 | var mday = (new Date()).toString().split(' ').splice(0); 5 | mday = mday[0]; 6 | var mdate = (new Date()).toString().split(' ').splice(1,4).join(' '); 7 | document.title = mday + ", " + mdate + " :NOC: nginx VTS Monitor"; 8 | } 9 | 10 | // change the title of the page to suit your needs 11 | // document.title = "Your company name, NOC: nginx Vhost Traffic Status Monitor"; 12 | 13 | // change the title of the page to suit your needs and include a clock 14 | // updatetimedate(); 15 | // setInterval(updatetimedate, 10000); 16 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/vhts/vtsvalues.js: -------------------------------------------------------------------------------- 1 | // vts values 2 | 3 | // base location of vts 4 | var locationngxvtstatus = "ngxvtstatus"; 5 | 6 | // vtsUpdateInterval, 2500=2,5seconds 7 | var vtsUpdateIntervalvv = 2500; 8 | 9 | // Streams that are down color in red 10 | var vtsupstreamdown = "background:red; color:white;"; 11 | 12 | // Waiting connections color in red when above trigger value 13 | var vtsconnwaiting = "background:red; color:white;"; 14 | var vtsconnwaitingtrigger = 1000; 15 | -------------------------------------------------------------------------------- /nginx-rtmp/conf/win-utf: -------------------------------------------------------------------------------- 1 | 2 | # This map is not a full windows-1251 <> utf8 map: it does not 3 | # contain Serbian and Macedonian letters. If you need a full map, 4 | # use contrib/unicode2nginx/win-utf map instead. 5 | 6 | charset_map windows-1251 utf-8 { 7 | 8 | 82 E2809A ; # single low-9 quotation mark 9 | 10 | 84 E2809E ; # double low-9 quotation mark 11 | 85 E280A6 ; # ellipsis 12 | 86 E280A0 ; # dagger 13 | 87 E280A1 ; # double dagger 14 | 88 E282AC ; # euro 15 | 89 E280B0 ; # per mille 16 | 17 | 91 E28098 ; # left single quotation mark 18 | 92 E28099 ; # right single quotation mark 19 | 93 E2809C ; # left double quotation mark 20 | 94 E2809D ; # right double quotation mark 21 | 95 E280A2 ; # bullet 22 | 96 E28093 ; # en dash 23 | 97 E28094 ; # em dash 24 | 25 | 99 E284A2 ; # trade mark sign 26 | 27 | A0 C2A0 ; #   28 | A1 D18E ; # capital Byelorussian short U 29 | A2 D19E ; # small Byelorussian short u 30 | 31 | A4 C2A4 ; # currency sign 32 | A5 D290 ; # capital Ukrainian soft G 33 | A6 C2A6 ; # borken bar 34 | A7 C2A7 ; # section sign 35 | A8 D081 ; # capital YO 36 | A9 C2A9 ; # (C) 37 | AA D084 ; # capital Ukrainian YE 38 | AB C2AB ; # left-pointing double angle quotation mark 39 | AC C2AC ; # not sign 40 | AD C2AD ; # soft hypen 41 | AE C2AE ; # (R) 42 | AF D087 ; # capital Ukrainian YI 43 | 44 | B0 C2B0 ; # ° 45 | B1 C2B1 ; # plus-minus sign 46 | B2 D086 ; # capital Ukrainian I 47 | B3 D196 ; # small Ukrainian i 48 | B4 D291 ; # small Ukrainian soft g 49 | B5 C2B5 ; # micro sign 50 | B6 C2B6 ; # pilcrow sign 51 | B7 C2B7 ; # · 52 | B8 D191 ; # small yo 53 | B9 E28496 ; # numero sign 54 | BA D194 ; # small Ukrainian ye 55 | BB C2BB ; # right-pointing double angle quotation mark 56 | 57 | BF D197 ; # small Ukrainian yi 58 | 59 | C0 D090 ; # capital A 60 | C1 D091 ; # capital B 61 | C2 D092 ; # capital V 62 | C3 D093 ; # capital G 63 | C4 D094 ; # capital D 64 | C5 D095 ; # capital YE 65 | C6 D096 ; # capital ZH 66 | C7 D097 ; # capital Z 67 | C8 D098 ; # capital I 68 | C9 D099 ; # capital J 69 | CA D09A ; # capital K 70 | CB D09B ; # capital L 71 | CC D09C ; # capital M 72 | CD D09D ; # capital N 73 | CE D09E ; # capital O 74 | CF D09F ; # capital P 75 | 76 | D0 D0A0 ; # capital R 77 | D1 D0A1 ; # capital S 78 | D2 D0A2 ; # capital T 79 | D3 D0A3 ; # capital U 80 | D4 D0A4 ; # capital F 81 | D5 D0A5 ; # capital KH 82 | D6 D0A6 ; # capital TS 83 | D7 D0A7 ; # capital CH 84 | D8 D0A8 ; # capital SH 85 | D9 D0A9 ; # capital SHCH 86 | DA D0AA ; # capital hard sign 87 | DB D0AB ; # capital Y 88 | DC D0AC ; # capital soft sign 89 | DD D0AD ; # capital E 90 | DE D0AE ; # capital YU 91 | DF D0AF ; # capital YA 92 | 93 | E0 D0B0 ; # small a 94 | E1 D0B1 ; # small b 95 | E2 D0B2 ; # small v 96 | E3 D0B3 ; # small g 97 | E4 D0B4 ; # small d 98 | E5 D0B5 ; # small ye 99 | E6 D0B6 ; # small zh 100 | E7 D0B7 ; # small z 101 | E8 D0B8 ; # small i 102 | E9 D0B9 ; # small j 103 | EA D0BA ; # small k 104 | EB D0BB ; # small l 105 | EC D0BC ; # small m 106 | ED D0BD ; # small n 107 | EE D0BE ; # small o 108 | EF D0BF ; # small p 109 | 110 | F0 D180 ; # small r 111 | F1 D181 ; # small s 112 | F2 D182 ; # small t 113 | F3 D183 ; # small u 114 | F4 D184 ; # small f 115 | F5 D185 ; # small kh 116 | F6 D186 ; # small ts 117 | F7 D187 ; # small ch 118 | F8 D188 ; # small sh 119 | F9 D189 ; # small shch 120 | FA D18A ; # small hard sign 121 | FB D18B ; # small y 122 | FC D18C ; # small soft sign 123 | FD D18D ; # small e 124 | FE D18E ; # small yu 125 | FF D18F ; # small ya 126 | } 127 | -------------------------------------------------------------------------------- /nginx-rtmp/contrib/README: -------------------------------------------------------------------------------- 1 | 2 | geo2nginx.pl by Andrei Nigmatulin 3 | 4 | The perl script to convert CSV geoip database ( free download 5 | at http://www.maxmind.com/app/geoip_country ) to format, suitable 6 | for use by the ngx_http_geo_module. 7 | 8 | 9 | unicode2nginx by Maxim Dounin 10 | 11 | The perl script to convert unicode mappings ( available 12 | at http://www.unicode.org/Public/MAPPINGS/ ) to the nginx 13 | configuration file format. 14 | Two generated full maps for windows-1251 and koi8-r. 15 | 16 | 17 | vim by Evan Miller 18 | 19 | Syntax highlighting of nginx configuration for vim, to be 20 | placed into ~/.vim/. 21 | 22 | -------------------------------------------------------------------------------- /nginx-rtmp/contrib/geo2nginx.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # (c) Andrei Nigmatulin, 2005 4 | # 5 | # this script provided "as is", without any warranties. use it at your own risk. 6 | # 7 | # special thanx to Andrew Sitnikov for perl port 8 | # 9 | # this script converts CSV geoip database (free download at http://www.maxmind.com/app/geoip_country) 10 | # to format, suitable for use with nginx_http_geo module (http://sysoev.ru/nginx) 11 | # 12 | # for example, line with ip range 13 | # 14 | # "62.16.68.0","62.16.127.255","1041253376","1041268735","RU","Russian Federation" 15 | # 16 | # will be converted to four subnetworks: 17 | # 18 | # 62.16.68.0/22 RU; 19 | # 62.16.72.0/21 RU; 20 | # 62.16.80.0/20 RU; 21 | # 62.16.96.0/19 RU; 22 | 23 | 24 | use warnings; 25 | use strict; 26 | 27 | while( ){ 28 | if (/"[^"]+","[^"]+","([^"]+)","([^"]+)","([^"]+)"/){ 29 | print_subnets($1, $2, $3); 30 | } 31 | } 32 | 33 | sub print_subnets { 34 | my ($a1, $a2, $c) = @_; 35 | my $l; 36 | while ($a1 <= $a2) { 37 | for ($l = 0; ($a1 & (1 << $l)) == 0 && ($a1 + ((1 << ($l + 1)) - 1)) <= $a2; $l++){}; 38 | print long2ip($a1) . "/" . (32 - $l) . " " . $c . ";\n"; 39 | $a1 += (1 << $l); 40 | } 41 | } 42 | 43 | sub long2ip { 44 | my $ip = shift; 45 | 46 | my $str = 0; 47 | 48 | $str = ($ip & 255); 49 | 50 | $ip >>= 8; 51 | $str = ($ip & 255).".$str"; 52 | 53 | $ip >>= 8; 54 | $str = ($ip & 255).".$str"; 55 | 56 | $ip >>= 8; 57 | $str = ($ip & 255).".$str"; 58 | } 59 | -------------------------------------------------------------------------------- /nginx-rtmp/contrib/unicode2nginx/unicode-to-nginx.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Convert unicode mappings to nginx configuration file format. 4 | 5 | # You may find useful mappings in various places, including 6 | # unicode.org official site: 7 | # 8 | # http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT 9 | # http://www.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT 10 | 11 | # Needs perl 5.6 or later. 12 | 13 | # Written by Maxim Dounin, mdounin@rambler-co.ru 14 | 15 | ############################################################################### 16 | 17 | require 5.006; 18 | 19 | while (<>) { 20 | # Skip comments and empty lines 21 | 22 | next if /^#/; 23 | next if /^\s*$/; 24 | chomp; 25 | 26 | # Convert mappings 27 | 28 | if (/^\s*0x(..)\s*0x(....)\s*(#.*)/) { 29 | # Mapping "#" 30 | my $cs_code = $1; 31 | my $un_code = $2; 32 | my $un_name = $3; 33 | 34 | # Produce UTF-8 sequence from character code; 35 | 36 | my $un_utf8 = join('', map { sprintf("%02X", $_) } unpack("C*", pack("U", hex($un_code)))); 37 | 38 | print " $cs_code $un_utf8 ; $un_name\n"; 39 | 40 | } else { 41 | warn "Unrecognized line: '$_'"; 42 | } 43 | } 44 | 45 | ############################################################################### 46 | -------------------------------------------------------------------------------- /nginx-rtmp/contrib/vim/ftdetect/nginx.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.nginx set ft=nginx 2 | au BufRead,BufNewFile */etc/nginx/* set ft=nginx 3 | au BufRead,BufNewFile */usr/local/nginx/conf/* set ft=nginx 4 | au BufRead,BufNewFile nginx.conf set ft=nginx 5 | -------------------------------------------------------------------------------- /nginx-rtmp/contrib/vim/indent/nginx.vim: -------------------------------------------------------------------------------- 1 | if exists("b:did_indent") 2 | finish 3 | endif 4 | let b:did_indent = 1 5 | 6 | setlocal indentexpr= 7 | 8 | " cindent actually works for nginx' simple file structure 9 | setlocal cindent 10 | " Just make sure that the comments are not reset as defs would be. 11 | setlocal cinkeys-=0# 12 | -------------------------------------------------------------------------------- /nginx-rtmp/docs/LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2002-2013 Igor Sysoev 3 | * Copyright (C) 2011-2013 Nginx, Inc. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | -------------------------------------------------------------------------------- /nginx-rtmp/docs/PCRE.LICENCE: -------------------------------------------------------------------------------- 1 | PCRE LICENCE 2 | ------------ 3 | 4 | PCRE is a library of functions to support regular expressions whose syntax 5 | and semantics are as close as possible to those of the Perl 5 language. 6 | 7 | Release 8 of PCRE is distributed under the terms of the "BSD" licence, as 8 | specified below. The documentation for PCRE, supplied in the "doc" 9 | directory, is distributed under the same terms as the software itself. 10 | 11 | The basic library functions are written in C and are freestanding. Also 12 | included in the distribution is a set of C++ wrapper functions, and a 13 | just-in-time compiler that can be used to optimize pattern matching. These 14 | are both optional features that can be omitted when the library is built. 15 | 16 | 17 | THE BASIC LIBRARY FUNCTIONS 18 | --------------------------- 19 | 20 | Written by: Philip Hazel 21 | Email local part: ph10 22 | Email domain: cam.ac.uk 23 | 24 | University of Cambridge Computing Service, 25 | Cambridge, England. 26 | 27 | Copyright (c) 1997-2013 University of Cambridge 28 | All rights reserved. 29 | 30 | 31 | PCRE JUST-IN-TIME COMPILATION SUPPORT 32 | ------------------------------------- 33 | 34 | Written by: Zoltan Herczeg 35 | Email local part: hzmester 36 | Emain domain: freemail.hu 37 | 38 | Copyright(c) 2010-2013 Zoltan Herczeg 39 | All rights reserved. 40 | 41 | 42 | STACK-LESS JUST-IN-TIME COMPILER 43 | -------------------------------- 44 | 45 | Written by: Zoltan Herczeg 46 | Email local part: hzmester 47 | Emain domain: freemail.hu 48 | 49 | Copyright(c) 2009-2013 Zoltan Herczeg 50 | All rights reserved. 51 | 52 | 53 | THE C++ WRAPPER FUNCTIONS 54 | ------------------------- 55 | 56 | Contributed by: Google Inc. 57 | 58 | Copyright (c) 2007-2012, Google Inc. 59 | All rights reserved. 60 | 61 | 62 | THE "BSD" LICENCE 63 | ----------------- 64 | 65 | Redistribution and use in source and binary forms, with or without 66 | modification, are permitted provided that the following conditions are met: 67 | 68 | * Redistributions of source code must retain the above copyright notice, 69 | this list of conditions and the following disclaimer. 70 | 71 | * Redistributions in binary form must reproduce the above copyright 72 | notice, this list of conditions and the following disclaimer in the 73 | documentation and/or other materials provided with the distribution. 74 | 75 | * Neither the name of the University of Cambridge nor the name of Google 76 | Inc. nor the names of their contributors may be used to endorse or 77 | promote products derived from this software without specific prior 78 | written permission. 79 | 80 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 81 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 82 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 83 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 84 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 85 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 86 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 87 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 88 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 89 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 90 | POSSIBILITY OF SUCH DAMAGE. 91 | 92 | End 93 | -------------------------------------------------------------------------------- /nginx-rtmp/docs/README: -------------------------------------------------------------------------------- 1 | 2 | Documentation is available at http://nginx.org 3 | 4 | -------------------------------------------------------------------------------- /nginx-rtmp/docs/zlib.LICENSE: -------------------------------------------------------------------------------- 1 | (C) 1995-2013 Jean-loup Gailly and Mark Adler 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | 19 | Jean-loup Gailly Mark Adler 20 | jloup@gzip.org madler@alumni.caltech.edu 21 | -------------------------------------------------------------------------------- /nginx-rtmp/html/50x.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Error 5 | 12 | 13 | 14 |

An error occurred.

15 |

Sorry, the page you are looking for is currently unavailable.
16 | Please try again later.

17 |

If you are the system administrator of this resource then you should check 18 | the error log for details.

19 |

Faithfully yours, nginx.

20 | 21 | 22 | -------------------------------------------------------------------------------- /nginx-rtmp/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Welcome to nginx! 5 | 12 | 13 | 14 |

Welcome to nginx!

15 |

If you see this page, the nginx web server is successfully installed and 16 | working. Further configuration is required.

17 | 18 |

For online documentation and support please refer to 19 | nginx.org.
20 | Commercial support is available at 21 | nginx.com.

22 | Windows documentation and support is available at 23 | nginx for Windows.
24 | Windows commercial support is available at 25 | ITProjectPartner.

26 | 27 |

Thank you for using nginx.

28 | 29 | 30 | -------------------------------------------------------------------------------- /nginx-rtmp/logs/access.log: -------------------------------------------------------------------------------- 1 | 127.0.0.1 - - [10/May/2019:15:24:28 +0800] "GET /hls/test.m3u8 HTTP/1.1" 206 223 "-" "Lavf/57.48.103" 2 | 127.0.0.1 - - [10/May/2019:15:24:29 +0800] "GET /hls/test-4.ts HTTP/1.1" 200 285572 "-" "Lavf/57.48.103" 3 | 127.0.0.1 - - [10/May/2019:15:24:29 +0800] "GET /hls/test-5.ts HTTP/1.1" 200 290272 "-" "Lavf/57.48.103" 4 | 127.0.0.1 - - [10/May/2019:15:24:32 +0800] "GET /hls/test-6.ts HTTP/1.1" 200 310576 "-" "Lavf/57.48.103" 5 | 127.0.0.1 - - [10/May/2019:15:24:34 +0800] "GET /hls/test.m3u8 HTTP/1.1" 200 223 "-" "Lavf/57.48.103" 6 | 127.0.0.1 - - [10/May/2019:15:24:34 +0800] "GET /hls/test-7.ts HTTP/1.1" 200 241768 "-" "Lavf/57.48.103" 7 | -------------------------------------------------------------------------------- /nginx-rtmp/logs/error.log: -------------------------------------------------------------------------------- 1 | 2019/05/10 15:11:04 [emerg] 6420#8756: CreateFile() "D:\1\nginx 1.7.11.3 Gryphon/conf/nginx.conf" failed (2: The system cannot find the file specified) 2 | 2019/05/10 15:14:51 [emerg] 8764#5852: CreateDirectory() "/tmp/app" failed (3: The system cannot find the path specified) 3 | 2019/05/10 15:15:25 [emerg] 8208#2600: CreateDirectory() "/tmp/app" failed (3: The system cannot find the path specified) 4 | 2019/05/10 15:16:02 [emerg] 7656#3376: CreateDirectory() "/tmp/app" failed (3: The system cannot find the path specified) 5 | 2019/05/10 15:19:03 [emerg] 5416#7412: CreateDirectory() "/tmp/app" failed (3: The system cannot find the path specified) 6 | 2019/05/10 15:19:05 [emerg] 7940#9424: CreateDirectory() "/tmp/app" failed (3: The system cannot find the path specified) 7 | 2019/05/10 15:19:06 [emerg] 6684#10072: CreateDirectory() "/tmp/app" failed (3: The system cannot find the path specified) 8 | 2019/05/10 15:20:38 [emerg] 7696#9972: CreateDirectory() "nginx-rtmp-module/tmp/app/" failed (3: The system cannot find the path specified) 9 | 2019/05/10 15:21:01 [notice] 9580#8372: sockinit() attempting to access sockapi 10 | 2019/05/10 15:21:01 [notice] 9580#8372: Access to sockapi succeded! 11 | 2019/05/10 15:21:01 [notice] 9580#8372: using sockapi from "4;108;" 12 | 2019/05/10 15:22:32 [notice] 6908#6504: sockinit() attempting to access sockapi 13 | 2019/05/10 15:22:32 [notice] 6908#6504: Access to sockapi succeded! 14 | 2019/05/10 15:22:32 [notice] 6908#6504: using sockapi from "4;36;" 15 | 2019/05/10 15:22:57 [notice] 5540#6344: sockinit() attempting to access sockapi 16 | 2019/05/10 15:22:57 [notice] 5540#6344: Access to sockapi succeded! 17 | 2019/05/10 15:22:57 [notice] 5540#6344: using sockapi from "4;36;" 18 | -------------------------------------------------------------------------------- /nginx-rtmp/logs/nginx.pid: -------------------------------------------------------------------------------- 1 | 3924 2 | -------------------------------------------------------------------------------- /nginx-rtmp/lua51.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/lua51.dll -------------------------------------------------------------------------------- /nginx-rtmp/nginx.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/nginx.exe -------------------------------------------------------------------------------- /nginx-rtmp/nginx_basic.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/nginx_basic.exe -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-0.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-0.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-1.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-1.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-10.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-10.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-11.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-11.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-12.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-12.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-2.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-2.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-3.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-3.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-4.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-4.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-5.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-5.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-6.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-6.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-7.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-7.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-8.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-8.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test-9.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeaHaige/m3u8player/e4532d9a3200264bdd70119ea82bba9458df04ba/nginx-rtmp/tmp/app/test-9.ts -------------------------------------------------------------------------------- /nginx-rtmp/tmp/app/test.m3u8: -------------------------------------------------------------------------------- 1 | #EXTM3U 2 | #EXT-X-VERSION:3 3 | #EXT-X-MEDIA-SEQUENCE:6 4 | #EXT-X-TARGETDURATION:5 5 | #EXTINF:5.000, 6 | test-6.ts 7 | #EXTINF:5.000, 8 | test-7.ts 9 | #EXTINF:5.000, 10 | test-8.ts 11 | #EXTINF:5.000, 12 | test-9.ts 13 | #EXTINF:5.000, 14 | test-10.ts 15 | #EXTINF:5.000, 16 | test-11.ts 17 | --------------------------------------------------------------------------------