├── LICENSE.md ├── flash ├── lib │ ├── osmf │ │ └── OSMF.swc │ ├── jw5 │ │ └── jwplayer-5-lib.swc │ └── jw6 │ │ └── jwplayer-6-lib.swc ├── src │ ├── org │ │ └── mangui │ │ │ ├── jwplayer │ │ │ └── media │ │ │ │ ├── HLSProvider6.as │ │ │ │ └── HLSProvider.as │ │ │ ├── HLS │ │ │ ├── HLSTypes.as │ │ │ ├── HLSStates.as │ │ │ ├── utils │ │ │ │ └── Log.as │ │ │ ├── parsing │ │ │ │ ├── Fragment.as │ │ │ │ ├── Manifest.as │ │ │ │ └── Level.as │ │ │ ├── muxing │ │ │ │ ├── FLV.as │ │ │ │ ├── PES.as │ │ │ │ ├── Tag.as │ │ │ │ ├── AAC.as │ │ │ │ ├── AVC.as │ │ │ │ └── TS.as │ │ │ ├── HLSEvent.as │ │ │ ├── HLS.as │ │ │ └── streaming │ │ │ │ ├── ManifestLoader.as │ │ │ │ ├── HLSNetStream.as │ │ │ │ └── FragmentLoader.as │ │ │ └── osmf │ │ │ └── plugins │ │ │ ├── HLSTimeTrait.as │ │ │ ├── HLSPlugin.as │ │ │ ├── HLSNetLoader.as │ │ │ └── HLSLoaderBase.as │ ├── HLSOSMFDynamicPlugin.as │ └── ChromelessPlayer.as ├── README.md └── LICENSE.md ├── javascript ├── font │ ├── self.eot │ ├── self.ttf │ ├── self.woff │ ├── vjs.eot │ ├── vjs.ttf │ ├── vjs.woff │ ├── self.svg │ └── vjs.svg ├── LICENSE.md ├── ie9.css └── ie8.css └── README.markdown /LICENSE.md: -------------------------------------------------------------------------------- 1 | see the flash and javascript directories for licenses 2 | -------------------------------------------------------------------------------- /flash/lib/osmf/OSMF.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/flash/lib/osmf/OSMF.swc -------------------------------------------------------------------------------- /javascript/font/self.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/javascript/font/self.eot -------------------------------------------------------------------------------- /javascript/font/self.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/javascript/font/self.ttf -------------------------------------------------------------------------------- /javascript/font/self.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/javascript/font/self.woff -------------------------------------------------------------------------------- /javascript/font/vjs.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/javascript/font/vjs.eot -------------------------------------------------------------------------------- /javascript/font/vjs.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/javascript/font/vjs.ttf -------------------------------------------------------------------------------- /javascript/font/vjs.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/javascript/font/vjs.woff -------------------------------------------------------------------------------- /flash/lib/jw5/jwplayer-5-lib.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/flash/lib/jw5/jwplayer-5-lib.swc -------------------------------------------------------------------------------- /flash/lib/jw6/jwplayer-6-lib.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/flash/lib/jw6/jwplayer-6-lib.swc -------------------------------------------------------------------------------- /flash/src/org/mangui/jwplayer/media/HLSProvider6.as: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjarnoldus/momovi-video-hls/HEAD/flash/src/org/mangui/jwplayer/media/HLSProvider6.as -------------------------------------------------------------------------------- /flash/src/HLSOSMFDynamicPlugin.as: -------------------------------------------------------------------------------- 1 | package 2 | { 3 | import flash.display.Sprite; 4 | import flash.system.Security; 5 | 6 | import org.mangui.osmf.plugins.HLSPlugin; 7 | import org.osmf.media.PluginInfo; 8 | 9 | public class HLSOSMFDynamicPlugin extends Sprite 10 | { 11 | private var _pluginInfo:PluginInfo; 12 | 13 | public function HLSOSMFDynamicPlugin() 14 | { 15 | super(); 16 | Security.allowDomain("*"); 17 | _pluginInfo = new HLSPlugin(); 18 | } 19 | 20 | public function get pluginInfo():PluginInfo{ 21 | return _pluginInfo; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /javascript/font/self.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright (C) 2014 by original authors @ fontello.com 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /javascript/LICENSE.md: -------------------------------------------------------------------------------- 1 | design - Copyright 2014 momovi, momovi.com 2 | hls flash integration - Copyright 2014 momovi, momovi.com 3 | original videojs - Copyright 2013 Brightcove, Inc. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. -------------------------------------------------------------------------------- /flash/src/org/mangui/HLS/HLSTypes.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.HLS { 15 | 16 | 17 | /** Identifiers for the different stream types. **/ 18 | public class HLSTypes { 19 | 20 | 21 | /** Identifier for live events. **/ 22 | public static const LIVE:String = "LIVE"; 23 | /** Identifier for on demand clips. **/ 24 | public static const VOD:String = "VOD"; 25 | 26 | 27 | } 28 | 29 | 30 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/HLS/HLSStates.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.HLS { 15 | 16 | 17 | /** Identifiers for the different playback states. **/ 18 | public class HLSStates { 19 | 20 | 21 | /** Identifiers for the idle state. **/ 22 | public static const IDLE:String = "IDLE"; 23 | /** Identifier for the buffering state. **/ 24 | public static const BUFFERING:String = "BUFFERING"; 25 | /** Identifier for the playing state. **/ 26 | public static const PLAYING:String = "PLAYING"; 27 | /** Identifier for the paused state. **/ 28 | public static const PAUSED:String = "PAUSED"; 29 | 30 | 31 | } 32 | 33 | 34 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/HLS/utils/Log.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.HLS.utils { 15 | 16 | 17 | import flash.external.ExternalInterface; 18 | 19 | 20 | /** Class that sends log messages to browser console. **/ 21 | public class Log { 22 | 23 | 24 | public static var LOGGING:Boolean = true; 25 | 26 | 27 | /** Log a message to the console. **/ 28 | public static function txt(message:*):void { 29 | if(LOGGING){ 30 | if(ExternalInterface.available) 31 | ExternalInterface.call('console.log',String(message)); 32 | else trace(message); 33 | } 34 | }; 35 | 36 | 37 | }; 38 | 39 | 40 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/osmf/plugins/HLSTimeTrait.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.osmf.plugins 15 | { 16 | import org.osmf.traits.TimeTrait; 17 | 18 | import org.mangui.HLS.HLS; 19 | import org.mangui.HLS.HLSEvent; 20 | import org.mangui.HLS.utils.*; 21 | 22 | public class HLSTimeTrait extends TimeTrait 23 | { 24 | private var _hls:HLS; 25 | private var _duration:Number = 0; 26 | private var _position:Number = 0; 27 | public function HLSTimeTrait(hls:HLS,duration:Number=0) 28 | { 29 | super(duration); 30 | _duration = duration; 31 | _hls = hls; 32 | _hls.addEventListener(HLSEvent.MEDIA_TIME,_mediaTimeHandler); 33 | } 34 | 35 | override public function get duration():Number 36 | { 37 | return _duration; 38 | } 39 | 40 | override public function get currentTime():Number 41 | { 42 | //Log.txt("HLSTimeTrait:get currentTime:" + _position); 43 | return _position; 44 | } 45 | 46 | /** Update playback position/duration **/ 47 | private function _mediaTimeHandler(event:HLSEvent):void { 48 | _position = event.mediatime.position; 49 | _duration = event.mediatime.duration; 50 | }; 51 | } 52 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/osmf/plugins/HLSPlugin.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.osmf.plugins 15 | { 16 | import org.osmf.elements.LoadFromDocumentElement; 17 | import org.osmf.media.MediaElement; 18 | import org.osmf.media.MediaFactoryItem; 19 | import org.osmf.media.MediaFactoryItemType; 20 | import org.osmf.media.MediaResourceBase; 21 | import org.osmf.media.PluginInfo; 22 | import org.osmf.media.URLResource; 23 | 24 | public class HLSPlugin extends PluginInfo 25 | { 26 | public function HLSPlugin(items:Vector.=null, elementCreationNotifFunc:Function=null){ 27 | 28 | items = new Vector.(); 29 | items.push( 30 | new MediaFactoryItem( 31 | 'org.mangui.osmf.plugins.HLSPlugin', 32 | canHandleResource, 33 | createMediaElement, 34 | MediaFactoryItemType.STANDARD 35 | ) 36 | ); 37 | 38 | super(items, elementCreationNotifFunc); 39 | } 40 | 41 | private function canHandleResource(resource:MediaResourceBase):Boolean{ 42 | return HLSLoaderBase.canHandle(resource); 43 | } 44 | 45 | private function createMediaElement():MediaElement{ 46 | return new LoadFromDocumentElement(null, new HLSLoaderBase()); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /javascript/ie9.css: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------- 2 | Copyright (c) 2014 wecast.it groep B.V. 3 | 4 | Licensed to the Apache Software Foundation (ASF) under one 5 | or more contributor license agreements. See the NOTICE file 6 | distributed with this work for additional information 7 | regarding copyright ownership. The ASF licenses this file 8 | to you under the Apache License, Version 2.0 (the 9 | "License"); you may not use this file except in compliance 10 | with the License. You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, 15 | software distributed under the License is distributed on an 16 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 | KIND, either express or implied. See the License for the 18 | specific language governing permissions and limitations 19 | under the License. 20 | 21 | Authors: 22 | John Davies 23 | 24 | --------------------------------------------------------------------------------*/ 25 | 26 | .vjs-default-skin .vjs-fullscreen-control:before { 27 | content: "\e000"; 28 | margin-left: 5px; 29 | font-size: 14px; 30 | line-height: 3; 31 | top: -3px; 32 | } 33 | 34 | .vjs-default-skin .vjs-seek-handle:before { 35 | top: -7px; 36 | left: -0.2em; 37 | } 38 | 39 | .vjs-default-skin .vjs-volume-handle:before { 40 | top: -5px; 41 | left: -0.5em; 42 | } 43 | 44 | .modal { 45 | display: block; 46 | position: fixed; 47 | top: 0; 48 | bottom: 0; 49 | left: 0; 50 | right: 0; 51 | margin: 0; 52 | background: #000; 53 | padding: 20px; 54 | z-index: 950; 55 | } 56 | 57 | 58 | .down-select { 59 | color: #fff; 60 | } 61 | 62 | .down-select:focus { 63 | color: #fff; 64 | } 65 | 66 | .down-select option { 67 | color: #fff; 68 | background: #000; 69 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/HLS/parsing/Fragment.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.HLS.parsing { 15 | 16 | 17 | /** HLS streaming chunk. **/ 18 | public class Fragment { 19 | 20 | 21 | /** Duration of this chunk. **/ 22 | public var duration:Number; 23 | /** Start time of this chunk. **/ 24 | public var start_time:Number; 25 | /** Start PTS of this chunk. **/ 26 | public var start_pts:Number; 27 | /** computed Start PTS of this chunk. **/ 28 | public var start_pts_computed:Number; 29 | /** sequence number of this chunk. **/ 30 | public var seqnum:Number; 31 | /** URL to this chunk. **/ 32 | public var url:String; 33 | /** continuity index of this chunk. **/ 34 | public var continuity:Number; 35 | 36 | 37 | 38 | /** Create the fragment. **/ 39 | public function Fragment(url:String, duration:Number, seqnum:Number,start_time:Number,continuity:Number):void { 40 | this.duration = duration; 41 | this.url = url; 42 | this.seqnum = seqnum; 43 | this.start_time = start_time; 44 | this.continuity = continuity; 45 | this.start_pts = Number.NEGATIVE_INFINITY; 46 | this.start_pts_computed = Number.NEGATIVE_INFINITY; 47 | }; 48 | } 49 | 50 | 51 | } -------------------------------------------------------------------------------- /javascript/ie8.css: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------- 2 | Copyright (c) 2014 wecast.it groep B.V. 3 | 4 | Licensed to the Apache Software Foundation (ASF) under one 5 | or more contributor license agreements. See the NOTICE file 6 | distributed with this work for additional information 7 | regarding copyright ownership. The ASF licenses this file 8 | to you under the Apache License, Version 2.0 (the 9 | "License"); you may not use this file except in compliance 10 | with the License. You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, 15 | software distributed under the License is distributed on an 16 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 | KIND, either express or implied. See the License for the 18 | specific language governing permissions and limitations 19 | under the License. 20 | 21 | Authors: 22 | John Davies 23 | 24 | --------------------------------------------------------------------------------*/ 25 | 26 | 27 | .vjs-default-skin .vjs-fullscreen-control:before { 28 | content: "\e000"; 29 | margin-left: 5px; 30 | font-size: 14px; 31 | line-height: 3; 32 | top: -3px; 33 | } 34 | 35 | .vjs-default-skin .vjs-seek-handle:before { 36 | top: -9px; 37 | left: -0.2em; 38 | } 39 | 40 | .vjs-default-skin .vjs-volume-handle:before { 41 | top: -7px; 42 | left: -0.5em; 43 | } 44 | 45 | .modal { 46 | display: block; 47 | position: fixed; 48 | top: 0; 49 | bottom: 0; 50 | left: 0; 51 | right: 0; 52 | margin: 0; 53 | background: #000; 54 | padding: 20px; 55 | z-index: 950; 56 | } 57 | 58 | 59 | .down-select { 60 | color: #fff; 61 | } 62 | 63 | .down-select:focus { 64 | color: #fff; 65 | } 66 | 67 | .down-select option { 68 | color: #fff; 69 | background: #000; 70 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/osmf/plugins/HLSNetLoader.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.osmf.plugins 15 | { 16 | import flash.net.NetConnection; 17 | import flash.net.NetStream; 18 | import org.osmf.media.MediaResourceBase; 19 | import org.osmf.media.URLResource; 20 | import org.osmf.net.NetStreamLoadTrait; 21 | import org.osmf.net.httpstreaming.HTTPStreamingNetLoader; 22 | import org.osmf.traits.LoadState; 23 | 24 | import org.mangui.HLS.HLS; 25 | import org.mangui.HLS.utils.*; 26 | 27 | public class HLSNetLoader extends HTTPStreamingNetLoader 28 | { 29 | 30 | private var _duration:Number; 31 | private var _hls:HLS; 32 | 33 | public function HLSNetLoader(hls:HLS,duration:Number){ 34 | _hls = hls; 35 | _duration = duration; 36 | super(); 37 | } 38 | 39 | override public function canHandleResource(resource:MediaResourceBase):Boolean 40 | { 41 | return true; 42 | } 43 | 44 | override protected function createNetStream(connection:NetConnection, resource:URLResource):NetStream 45 | { 46 | return _hls.stream; 47 | } 48 | 49 | override protected function processFinishLoading(loadTrait:NetStreamLoadTrait):void 50 | { 51 | var resource:URLResource = loadTrait.resource as URLResource; 52 | loadTrait.setTrait(new HLSTimeTrait(_hls,_duration)); 53 | updateLoadTrait(loadTrait, LoadState.READY); 54 | return; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Momovi.com HTML5 HLS video player 2 | 3 | The [momovi.com video hls player](https://momovi.com/opensource/momovi-video-hls) is a free to use, open source HTML5 HLS video player. 4 | Supported platforms: 5 | - all major browsers, including Safari, Chrome, FireFox, Internet Explorer; 6 | - Tablets, including iPad and Android 4.2+ 7 | - Smart phones, including iPhone, Android 4.2+ and Black Berry. 8 | 9 | ## Usage 10 | - Download the video player from [momovi.com video hls player](https://momovi.com/opensource/momovi-video-hls) 11 | - Unzip, extract and upload the content to your server 12 | - Configure the HTML to your needs 13 | 14 | ## Features 15 | 16 | - VoD & Live playlists 17 | - Adaptive streaming 18 | - Discontinuity support of video tracks 19 | - Supported by major desktop browsers, iOS, black berry and android 20 | - Configurable seeking method on VoD 21 | - Accurate seeking to exact requested position 22 | - Key frame based seeking (nearest key frame) 23 | - Segment based seeking (beginning of segment) 24 | - AES-128 decryption 25 | - Buffer progress report 26 | - Error resilience 27 | - Retry mechanism on I/O errors 28 | - Recovery mechanism on badly segmented TS streams 29 | 30 | ### Supported M3U8 tags 31 | 32 | - `#EXTM3U` 33 | - `#EXTINF` 34 | - `#EXT-X-STREAM-INF` (Multiple bitrate) 35 | - `#EXT-X-ENDLIST` (VoD / Live playlist) 36 | - `#EXT-X-MEDIA-SEQUENCE` 37 | - `#EXT-X-TARGETDURATION` 38 | - `#EXT-X-DISCONTINUITY` (VoD and Live playlist) 39 | - `#EXT-X-DISCONTINUITY-SEQUENCE` (VoD and Live playlist) 40 | - `#EXT-X-PROGRAM-DATE-TIME` (optional, used to synchronize time-stamps and sequence number when switching from one level to another) 41 | - `#EXT-X-KEY` (AES-128 method supported only) 42 | - `#EXT-X-BYTERANGE` 43 | 44 | 45 | 46 | ## Contributing 47 | The momovi.com video player is a free and open source library, and we appreciate any help you're willing to give. Contact us for bugs, feature requests and other questions at opensource@ . 48 | 49 | ## License 50 | The momovi.com video player is based on two open source projects, released under different licences 51 | 52 | - HTML5 video player: 53 | - hls flash integration - Copyright 2014-2015 Momovi.com, The Netherlands 54 | - original videojs - Copyright 2013 Brightcove, Inc. 55 | 56 | - HLS Flash player plugin: 57 | - discontinuity tag - Jeroen Arnoldus Copyright (c) 2014 58 | - original - Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/flashls) 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /flash/src/org/mangui/HLS/muxing/FLV.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.HLS.muxing { 15 | 16 | 17 | import flash.utils.ByteArray; 18 | 19 | 20 | /** Helpers for the FLV file format. **/ 21 | public class FLV { 22 | 23 | 24 | /** Return an EOS Video tag (16 bytes). **/ 25 | public static function getEosTag(stamp:Number):ByteArray { 26 | var tag:ByteArray = FLV.getTagHeader(false,5,stamp); 27 | // AVC Keyframe. 28 | tag.writeByte(0x17); 29 | // Sequence end, composition time 30 | tag.writeUnsignedInt(0x02000000); 31 | return tag; 32 | }; 33 | 34 | 35 | /** Get the FLV file header. **/ 36 | public static function getHeader():ByteArray { 37 | var flv:ByteArray = new ByteArray(); 38 | // "F" + "L" + "V". 39 | flv.writeByte(0x46); 40 | flv.writeByte(0x4C); 41 | flv.writeByte(0x56); 42 | // File version (1) 43 | flv.writeByte(1); 44 | // Audio + Video tags. 45 | flv.writeByte(1); 46 | // Length of the header. 47 | flv.writeUnsignedInt(9); 48 | // PreviousTagSize0 49 | flv.writeUnsignedInt(0); 50 | return flv; 51 | }; 52 | 53 | 54 | /** Get an FLV Tag header (11 bytes). **/ 55 | public static function getTagHeader(audio:Boolean,length:Number,stamp:Number):ByteArray { 56 | var tag:ByteArray = new ByteArray(); 57 | // Audio (8) or Video (9) tag 58 | if(audio) { 59 | tag.writeByte(8); 60 | } else { 61 | tag.writeByte(9); 62 | } 63 | // Size of the tag in bytes after StreamID. 64 | tag.writeByte(length >> 16); 65 | tag.writeByte(length >> 8); 66 | tag.writeByte(length); 67 | // Timestamp (lower 24 plus upper 8) 68 | tag.writeByte(stamp >> 16); 69 | tag.writeByte(stamp >> 8); 70 | tag.writeByte(stamp); 71 | tag.writeByte(stamp >> 24); 72 | // StreamID (3 empty bytes) 73 | tag.writeByte(0); 74 | tag.writeByte(0); 75 | tag.writeByte(0); 76 | // All done 77 | return tag; 78 | }; 79 | 80 | 81 | } 82 | 83 | 84 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/HLS/muxing/PES.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.HLS.muxing { 15 | 16 | 17 | import org.mangui.HLS.muxing.*; 18 | import org.mangui.HLS.utils.*; 19 | import flash.utils.ByteArray; 20 | 21 | 22 | /** Representation of a Packetized Elementary Stream. **/ 23 | public class PES { 24 | 25 | 26 | /** Timescale of pts/dts is 90khz. **/ 27 | public static var TIMESCALE:Number = 90; 28 | 29 | 30 | /** Is it AAC audio or AVC video. **/ 31 | public var audio:Boolean; 32 | /** The PES data (including headers). **/ 33 | public var data:ByteArray; 34 | /** Start of the payload. **/ 35 | public var payload:Number; 36 | /** Timestamp from the PTS header. **/ 37 | public var pts:Number; 38 | /** Timestamp from the DTS header. **/ 39 | public var dts:Number; 40 | 41 | 42 | /** Save the first chunk of PES data. **/ 43 | public function PES(dat:ByteArray,aud:Boolean) { 44 | data = dat; 45 | audio = aud; 46 | }; 47 | 48 | 49 | /** Append PES data from additional TS packets. **/ 50 | public function append(dat:ByteArray):void { 51 | data.writeBytes(dat,0,0); 52 | }; 53 | 54 | 55 | /** When all data is appended, parse the PES headers. **/ 56 | public function parse():void { 57 | data.position = 0; 58 | // Start code prefix and packet ID. 59 | var prefix:Number = data.readUnsignedInt(); 60 | /*Audio streams (0x1C0-0x1DF) 61 | Video streams (0x1E0-0x1EF) 62 | 0x1BD is special case, could be audio or video (ffmpeg\libavformat\mpeg.c) 63 | */ 64 | if((audio && (prefix > 0x1df || prefix < 0x1c0 && prefix !=0x1bd)) || 65 | (!audio && prefix != 0x1e0 && prefix != 0x1ea && prefix != 0x1bd)) { 66 | throw new Error("PES start code not found or not AAC/AVC: " + prefix); 67 | } 68 | // Ignore packet length and marker bits. 69 | data.position += 3; 70 | // Check for PTS 71 | var flags:uint = (data.readUnsignedByte() & 192) >> 6; 72 | if(flags != 2 && flags != 3) { 73 | throw new Error("No PTS/DTS in this PES packet"); 74 | } 75 | // Check PES header length 76 | var length:uint = data.readUnsignedByte(); 77 | // Grab the timestamp from PTS data (spread out over 5 bytes): 78 | // XXXX---X -------- -------X -------- -------X 79 | 80 | var _pts:Number = ((data.readUnsignedByte() & 0x0e) << 29) + 81 | ((data.readUnsignedShort() >> 1) << 15) + 82 | (data.readUnsignedShort() >> 1); 83 | length -= 5; 84 | var _dts:Number = _pts; 85 | if(flags == 3) { 86 | // Grab the DTS (like PTS) 87 | _dts = ((data.readUnsignedByte() & 0x0e) << 29) + 88 | ((data.readUnsignedShort() >> 1) << 15) + 89 | (data.readUnsignedShort() >> 1); 90 | length -= 5; 91 | } 92 | pts = Math.round(_pts / PES.TIMESCALE); 93 | dts = Math.round(_dts / PES.TIMESCALE); 94 | // Skip other header data and parse payload. 95 | data.position += length; 96 | payload = data.position; 97 | }; 98 | 99 | 100 | } 101 | 102 | 103 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/HLS/HLSEvent.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.HLS { 15 | 16 | 17 | import flash.events.Event; 18 | 19 | 20 | /** Event fired when an error prevents playback. **/ 21 | public class HLSEvent extends Event { 22 | 23 | 24 | /** Identifier for a playback complete event. **/ 25 | public static const PLAYBACK_COMPLETE:String = "hlsEventPlayBackComplete"; 26 | /** Identifier for a playback error event. **/ 27 | public static const ERROR:String = "hlsEventError"; 28 | /** Identifier for a fragment load event. **/ 29 | public static const FRAGMENT_LOADED:String = "hlsEventFragmentLoaded"; 30 | /** Identifier when last fragment of playlist has been loaded **/ 31 | public static const LAST_VOD_FRAGMENT_LOADED:String = "hlsEventLastFragmentLoaded"; 32 | /** Identifier for a manifest (re)load event. **/ 33 | public static const MANIFEST_LOADED:String = "hlsEventManifest"; 34 | /** Identifier for a playback media time change event. **/ 35 | public static const MEDIA_TIME:String = "hlsEventMediaTime"; 36 | /** Identifier for a playback state switch event. **/ 37 | public static const STATE:String = "hlsEventState"; 38 | /** Identifier for a quality level switch event. **/ 39 | public static const QUALITY_SWITCH:String = "hlsEventQualitySwitch"; 40 | /** Identifier for a level updated event (playlist loaded) **/ 41 | public static const LEVEL_UPDATED:String = "hlsEventLevelUpdated"; 42 | /** Identifier for a Level Time Stamp updated event (PTS updated) **/ 43 | public static const LEVEL_PTS_UPDATED:String = "hlsEventLevelPTSUpdated"; 44 | /** Identifier for a audio only fragment **/ 45 | public static const AUDIO_ONLY:String = "audioOnly"; 46 | 47 | /** The current quality level. **/ 48 | public var level:Number; 49 | /** The list with quality levels. **/ 50 | public var levels:Array; 51 | /** The error message. **/ 52 | public var message:String; 53 | /** The current QOS metrics. **/ 54 | public var metrics:Object; 55 | /** The time position. **/ 56 | public var mediatime:Object; 57 | /** The new playback state. **/ 58 | public var state:String; 59 | 60 | 61 | /** Assign event parameter and dispatch. **/ 62 | public function HLSEvent(type:String, parameter:*=null) { 63 | switch(type) { 64 | case HLSEvent.ERROR: 65 | message = parameter as String; 66 | break; 67 | case HLSEvent.FRAGMENT_LOADED: 68 | metrics = parameter as Object; 69 | break; 70 | case HLSEvent.MANIFEST_LOADED: 71 | levels = parameter as Array; 72 | break; 73 | case HLSEvent.MEDIA_TIME: 74 | mediatime = parameter as Object; 75 | break; 76 | case HLSEvent.STATE: 77 | state = parameter as String; 78 | break; 79 | case HLSEvent.QUALITY_SWITCH: 80 | level = parameter as Number; 81 | break; 82 | case HLSEvent.LEVEL_UPDATED: 83 | level = parameter as Number; 84 | break; 85 | case HLSEvent.LEVEL_PTS_UPDATED: 86 | level = parameter as Number; 87 | break; 88 | } 89 | super(type, false, false); 90 | }; 91 | 92 | 93 | } 94 | 95 | 96 | } -------------------------------------------------------------------------------- /flash/src/org/mangui/HLS/HLS.as: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------- 2 | // Copyright (c) 2014-2013 NoZAP B.V. 3 | // Copyright (c) 2013 Guillaume du Pontavice (https://github.com/mangui/HLSprovider) 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this 7 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 | // 9 | // Authors: 10 | // Jeroen Arnoldus 11 | // Guillaume du Pontavice 12 | //------------------------------------------------------------------------------- 13 | 14 | package org.mangui.HLS { 15 | 16 | 17 | import org.mangui.HLS.streaming.*; 18 | import org.mangui.HLS.utils.*; 19 | 20 | import flash.events.*; 21 | import flash.net.NetStream; 22 | import flash.net.NetConnection; 23 | 24 | /** Class that manages the streaming process. **/ 25 | public class HLS extends EventDispatcher { 26 | /** The quality monitor. **/ 27 | private var _fragmentLoader:FragmentLoader; 28 | /** The manifest parser. **/ 29 | private var _manifestLoader:ManifestLoader; 30 | /** HLS NetStream **/ 31 | private var _hlsNetStream:HLSNetStream; 32 | 33 | private var _client:Object = {}; 34 | 35 | /** Create and connect all components. **/ 36 | public function HLS():void { 37 | var connection:NetConnection = new NetConnection(); 38 | connection.connect(null); 39 | _manifestLoader = new ManifestLoader(this); 40 | _fragmentLoader = new FragmentLoader(this); 41 | _hlsNetStream = new HLSNetStream(connection,this, _fragmentLoader); 42 | }; 43 | 44 | 45 | /** Forward internal errors. **/ 46 | override public function dispatchEvent(event:Event):Boolean { 47 | if(event.type == HLSEvent.ERROR) { 48 | Log.txt(HLSEvent(event).message); 49 | _hlsNetStream.close(); 50 | } 51 | return super.dispatchEvent(event); 52 | }; 53 | 54 | 55 | /** Return the current quality level. **/ 56 | public function getLevel():Number { 57 | return _fragmentLoader.getLevel(); 58 | }; 59 | 60 | 61 | /** Return the list with bitrate levels. **/ 62 | public function getLevels():Array { 63 | return _manifestLoader.getLevels(); 64 | }; 65 | 66 | 67 | /** Return the list with switching metrics. **/ 68 | public function getMetrics():Object { 69 | return _fragmentLoader.getMetrics(); 70 | }; 71 | 72 | 73 | /** Return the current playback position. **/ 74 | public function getPosition():Number { 75 | return _hlsNetStream.getPosition(); 76 | }; 77 | 78 | 79 | /** Return the current playback position. **/ 80 | public function getState():String { 81 | return _hlsNetStream.getState(); 82 | }; 83 | 84 | 85 | /** Return the type of stream. **/ 86 | public function getType():String { 87 | return _manifestLoader.getType(); 88 | }; 89 | 90 | 91 | /** Start playing an new HLS stream. **/ 92 | public function play(url:String,start:Number=0):void { 93 | _hlsNetStream.close(); 94 | //_playbackStartPosition = start; 95 | _manifestLoader.load(url); 96 | }; 97 | 98 | /** Update the screen width. **/ 99 | public function setWidth(width:Number):void { 100 | _fragmentLoader.setWidth(width); 101 | }; 102 | 103 | /* update playback quality level */ 104 | public function setPlaybackQuality(level:Number):void { 105 | _fragmentLoader.setPlaybackQuality(level); 106 | _hlsNetStream.seek(_hlsNetStream.getPosition()); 107 | }; 108 | public function get stream():NetStream { 109 | return _hlsNetStream; 110 | } 111 | public function get client():Object { 112 | return _client; 113 | } 114 | public function set client(value:Object):void { 115 | _client = value; 116 | } 117 | } 118 | ; 119 | } -------------------------------------------------------------------------------- /flash/README.md: -------------------------------------------------------------------------------- 1 | #BUILD 2 | 3 | Unzip de zip in sdks to 4.6.0 4 | OS X issue: remove the -d32 option in $FLEXPATH/bin/mxmlc batch file of flash 5 | 6 | run the build.sh in builds 7 | 8 | The result is an OSMF player for StrobeMediaPlayback 9 | 10 | #PATCHES By momovi.com 11 | 12 | Now handles discontinuities in live streams automatically 13 | 14 | #TODO (but not really important) 15 | -Set player to Live or VOD (now hided in the webpage) 16 | -subtitles 17 | -test for multiple streams 18 | 19 | 20 | #HLSprovider 21 | 22 | **HLSProvider** is an AS3 plugin that allows you to play HLS playlist using either : 23 | 24 | * **Chromeless** Flash Player 25 | * **JWPlayer** Flash free edition version **5.x** 26 | * **JWPlayer** Flash free edition version **6.x** 27 | * **OSMF** version **2.0** (beta stage, any help welcomed !) 28 | 29 | 30 | **HLSProvider** supports the following features : 31 | 32 | * VOD/live/DVR playlists 33 | * multiple bitrate playlist / adaptive streaming 34 | * automatic quality switching, using serial segment fetching method described in [http://www.cs.tut.fi/%7Emoncef/publications/rate-adaptation-IC-2011.pdf](http://www.cs.tut.fi/%7Emoncef/publications/rate-adaptation-IC-2011.pdf) 35 | * manual quality switching (JWPlayer 6 only) 36 | * seeking in VoD and live playlist 37 | * buffer progress report 38 | * error resilience (retry mechanism in case of I/O Errors) 39 | * accurate seeking (seek to exact position,not to fragment boundary) 40 | 41 | the following M3U8 tags are supported: 42 | 43 | * #EXTM3U 44 | * #EXTINF 45 | * #EXT-X-STREAM-INF (used to support multiple bitrate) 46 | * #EXT-X-ENDLIST (supports live / event / VOD playlist) 47 | * #EXT-X-MEDIA-SEQUENCE (value is used for live playlist update) 48 | * #EXT-X-TARGETDURATION (value is used as live playlist reload interval) 49 | * #EXT-X-DISCONTINUITY 50 | 51 | ##HLSProvider in action : 52 | 53 | * http://streambox.fr/HLSProvider/chromeless 54 | * http://streambox.fr/HLSProvider/jwplayer5 55 | * http://streambox.fr/HLSProvider/jwplayer6 56 | * http://streambox.fr/HLSProvider/osmf 57 | 58 | 59 | ##How to use it : 60 | 61 | download package : https://github.com/mangui/HLSprovider/archive/master.zip 62 | 63 | ###jwplayer5 based setup: 64 | from zip, extract test/chromeless folder, and get inspired by example.html 65 | 66 | ###OSMF based setup: 67 | from zip, extract test/osmf folder, and get inspired by index.html 68 | 69 | ###jwplayer5 based setup: 70 | from zip, extract test/jwplayer5 folder, and get inspired by example.html 71 | 72 |
73 | 74 | 84 | 85 | ###jwplayer6 based setup: 86 | from zip, extract test/jwplayer6 folder, and get inspired by example.html 87 | 88 |
89 | 90 |