no commit message
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mangui.osmf.plugins.loader {
|
||||
import org.osmf.elements.proxyClasses.LoadFromDocumentLoadTrait;
|
||||
import org.osmf.events.LoadEvent;
|
||||
import org.osmf.media.MediaResourceBase;
|
||||
import org.osmf.traits.LoadState;
|
||||
import org.osmf.traits.LoadTrait;
|
||||
import org.osmf.traits.LoaderBase;
|
||||
import org.osmf.traits.MediaTraitType;
|
||||
import org.osmf.utils.OSMFStrings;
|
||||
import org.osmf.elements.ProxyElement;
|
||||
|
||||
/**
|
||||
* LoadFromDocumentElement is the base class for MediaElements that load documents
|
||||
* that contain information about the real MediaElement to expose. For example, the
|
||||
* contents of a SMIL document can be represented as a MediaElement, but until the
|
||||
* SMIL document is loaded, it's impossible to know what MediaElement the SMIL
|
||||
* document represents.
|
||||
*
|
||||
* <p>Because of the dynamic nature of this operation, a LoadFromDocumentElement extends
|
||||
* ProxyElement. When the document has been loaded, this class will set the
|
||||
* <code>proxiedElement</code> property to the MediaElement that was generated from
|
||||
* the document.</p>
|
||||
*
|
||||
* <p>This is an abstract base class, and must be subclassed.</p>
|
||||
*
|
||||
* <p>Note: It is simplest to use the MediaPlayer class in conjunction with subclasses of
|
||||
* the LoadFromDocumentElement. If you work directly with a LoadFromDocumentElement, then
|
||||
* it's important to listen for events related to traits being added and removed. If you
|
||||
* use the MediaPlayer class with a LoadFromDocumentElement, then the MediaPlayer will
|
||||
* automatically listen for these events for you.</p>
|
||||
*
|
||||
* @see org.osmf.elements.ProxyElement
|
||||
* @see org.osmf.media.MediaElement
|
||||
* @see org.osmf.media.MediaPlayer
|
||||
*
|
||||
* @langversion 3.0
|
||||
* @playerversion Flash 10
|
||||
* @playerversion AIR 1.5
|
||||
* @productversion OSMF 1.0
|
||||
*/
|
||||
public class HLSLoadFromDocumentElement extends ProxyElement {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param resource The resource associated with this element.
|
||||
* @param loader The LoaderBase used to load the resource. Cannot be null.
|
||||
*
|
||||
* @throws ArgumentError If loader is null.
|
||||
*
|
||||
* @langversion 3.0
|
||||
* @playerversion Flash 10
|
||||
* @playerversion AIR 1.5
|
||||
* @productversion OSMF 1.0
|
||||
*/
|
||||
public function HLSLoadFromDocumentElement(resource : MediaResourceBase = null, loader : LoaderBase = null) {
|
||||
super(null);
|
||||
|
||||
this.loader = loader;
|
||||
this.resource = resource;
|
||||
|
||||
if (loader == null) {
|
||||
throw new ArgumentError(OSMFStrings.getString(OSMFStrings.NULL_PARAM));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* Overriding is necessary because there is a null proxiedElement.
|
||||
*/
|
||||
override public function set resource(value : MediaResourceBase) : void {
|
||||
if (_resource != value && value != null) {
|
||||
_resource = value;
|
||||
loadTrait = new LoadFromDocumentLoadTrait(loader, resource);
|
||||
loadTrait.addEventListener(LoadEvent.LOAD_STATE_CHANGE, onLoadStateChange, false, int.MAX_VALUE);
|
||||
|
||||
if (super.getTrait(MediaTraitType.LOAD) != null) {
|
||||
super.removeTrait(MediaTraitType.LOAD);
|
||||
}
|
||||
super.addTrait(MediaTraitType.LOAD, loadTrait);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
override public function get resource() : MediaResourceBase {
|
||||
return _resource;
|
||||
}
|
||||
|
||||
private function onLoadStateChange(event : LoadEvent) : void {
|
||||
if (event.loadState == LoadState.READY) {
|
||||
event.stopImmediatePropagation();
|
||||
|
||||
// Remove the temporary LoadTrait.
|
||||
removeTrait(MediaTraitType.LOAD);
|
||||
|
||||
// Tell the soon-to-be proxied element to load itself.
|
||||
// Note that we do this before setting it as the proxied
|
||||
// element, so as to avoid dispatching a second LOADING
|
||||
// event.
|
||||
|
||||
// Set up a listener so that we can prevent the dispatch
|
||||
// of a second LOADING event.
|
||||
var proxiedLoadTrait : LoadTrait = loadTrait.mediaElement.getTrait(MediaTraitType.LOAD) as LoadTrait;
|
||||
proxiedLoadTrait.addEventListener(LoadEvent.LOAD_STATE_CHANGE, onProxiedElementLoadStateChange, false, int.MAX_VALUE);
|
||||
|
||||
// Expose the proxied element.
|
||||
proxiedElement = loadTrait.mediaElement;
|
||||
|
||||
// If our proxied element hasn't started loading yet, we should
|
||||
// initiate the load.
|
||||
if (proxiedLoadTrait.loadState == LoadState.UNINITIALIZED) {
|
||||
proxiedLoadTrait.load();
|
||||
}
|
||||
|
||||
function onProxiedElementLoadStateChange(event : LoadEvent) : void {
|
||||
if (event.loadState == LoadState.LOADING) {
|
||||
event.stopImmediatePropagation();
|
||||
} else {
|
||||
proxiedLoadTrait.removeEventListener(LoadEvent.LOAD_STATE_CHANGE, onProxiedElementLoadStateChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var _resource : MediaResourceBase;
|
||||
private var loadTrait : LoadFromDocumentLoadTrait;
|
||||
private var loader : LoaderBase;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
package org.mangui.osmf.plugins.loader {
|
||||
import org.mangui.hls.HLS;
|
||||
import org.mangui.hls.event.HLSEvent;
|
||||
import org.mangui.hls.model.Level;
|
||||
import org.mangui.hls.constant.HLSTypes;
|
||||
import org.mangui.osmf.plugins.HLSMediaElement;
|
||||
import org.mangui.osmf.plugins.utils.ErrorManager;
|
||||
import org.osmf.elements.proxyClasses.LoadFromDocumentLoadTrait;
|
||||
import org.osmf.events.MediaError;
|
||||
import org.osmf.events.MediaErrorEvent;
|
||||
import org.osmf.media.MediaElement;
|
||||
import org.osmf.media.MediaResourceBase;
|
||||
import org.osmf.media.URLResource;
|
||||
import org.osmf.net.DynamicStreamingItem;
|
||||
import org.osmf.net.DynamicStreamingResource;
|
||||
import org.osmf.net.StreamType;
|
||||
import org.osmf.net.StreamingURLResource;
|
||||
import org.osmf.traits.LoadState;
|
||||
import org.osmf.traits.LoadTrait;
|
||||
import org.osmf.traits.LoaderBase;
|
||||
|
||||
CONFIG::LOGGING {
|
||||
import org.mangui.hls.utils.Log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loader for .m3u8 playlist file.
|
||||
* Works like a F4MLoader
|
||||
*/
|
||||
public class HLSLoaderBase extends LoaderBase {
|
||||
private var _loadTrait : LoadTrait;
|
||||
/** Reference to the framework. **/
|
||||
private var _hls : HLS = null;
|
||||
|
||||
public function HLSLoaderBase() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static function canHandle(resource : MediaResourceBase) : Boolean {
|
||||
if (resource !== null && resource is URLResource) {
|
||||
var urlResource : URLResource = URLResource(resource);
|
||||
// check for m3u/m3u8
|
||||
if (urlResource.url.search(/(https?|file)\:\/\/.*?\m3u(\?.*)?/i) !== -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var contentType : Object = urlResource.getMetadataValue("content-type");
|
||||
if (contentType && contentType is String) {
|
||||
// If the filename doesn't include a .m3u or m3u8 extension, but
|
||||
// explicit content-type metadata is found on the
|
||||
// URLResource, we can handle it. Must be either of:
|
||||
// - "application/x-mpegURL"
|
||||
// - "vnd.apple.mpegURL"
|
||||
if ((contentType as String).search(/(application\/x-mpegURL|vnd.apple.mpegURL)/i) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override public function canHandleResource(resource : MediaResourceBase) : Boolean {
|
||||
return canHandle(resource);
|
||||
}
|
||||
|
||||
override protected function executeLoad(loadTrait : LoadTrait) : void {
|
||||
_loadTrait = loadTrait;
|
||||
updateLoadTrait(loadTrait, LoadState.LOADING);
|
||||
|
||||
if (_hls != null) {
|
||||
_hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
|
||||
_hls.removeEventListener(HLSEvent.ERROR, _errorHandler);
|
||||
_hls.dispose();
|
||||
_hls = null;
|
||||
}
|
||||
_hls = new HLS();
|
||||
_hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
|
||||
_hls.addEventListener(HLSEvent.ERROR, _errorHandler);
|
||||
/* load playlist */
|
||||
_hls.load(URLResource(loadTrait.resource).url);
|
||||
}
|
||||
|
||||
override protected function executeUnload(loadTrait : LoadTrait) : void {
|
||||
updateLoadTrait(loadTrait, LoadState.UNINITIALIZED);
|
||||
}
|
||||
|
||||
/** Update video A/R on manifest load. **/
|
||||
private function _manifestLoadedHandler(event : HLSEvent) : void {
|
||||
var resource : MediaResourceBase = URLResource(_loadTrait.resource);
|
||||
|
||||
// retrieve stream type
|
||||
var streamType : String = (resource as StreamingURLResource).streamType;
|
||||
if (streamType == null || streamType == StreamType.LIVE_OR_RECORDED) {
|
||||
if (_hls.type == HLSTypes.LIVE) {
|
||||
streamType = StreamType.LIVE;
|
||||
} else {
|
||||
streamType = StreamType.RECORDED;
|
||||
}
|
||||
}
|
||||
|
||||
var levels : Vector.<Level> = _hls.levels;
|
||||
var nbLevel : int = levels.length;
|
||||
var urlRes : URLResource = resource as URLResource;
|
||||
var dynamicRes : DynamicStreamingResource = new DynamicStreamingResource(urlRes.url);
|
||||
var streamItems : Vector.<DynamicStreamingItem> = new Vector.<DynamicStreamingItem>();
|
||||
|
||||
for (var i : int = 0; i < nbLevel; i++) {
|
||||
if (levels[i].width) {
|
||||
streamItems.push(new DynamicStreamingItem(level2label(levels[i]), levels[i].bitrate / 1024, levels[i].width, levels[i].height));
|
||||
} else {
|
||||
streamItems.push(new DynamicStreamingItem(level2label(levels[i]), levels[i].bitrate / 1024));
|
||||
}
|
||||
}
|
||||
dynamicRes.streamItems = streamItems;
|
||||
dynamicRes.initialIndex = _hls.startLevel;
|
||||
resource = dynamicRes;
|
||||
// set Stream Type
|
||||
var streamUrlRes : StreamingURLResource = resource as StreamingURLResource;
|
||||
streamUrlRes.streamType = streamType;
|
||||
try {
|
||||
var loadedElem : MediaElement = new HLSMediaElement(resource, _hls, event.levels[_hls.startLevel].duration);
|
||||
LoadFromDocumentLoadTrait(_loadTrait).mediaElement = loadedElem;
|
||||
updateLoadTrait(_loadTrait, LoadState.READY);
|
||||
} catch(e : Error) {
|
||||
updateLoadTrait(_loadTrait, LoadState.LOAD_ERROR);
|
||||
_loadTrait.dispatchEvent(new MediaErrorEvent(MediaErrorEvent.MEDIA_ERROR, false, false, new MediaError(e.errorID, e.message)));
|
||||
}
|
||||
};
|
||||
|
||||
private function level2label(level : Level) : String {
|
||||
if (level.name) {
|
||||
return level.name;
|
||||
} else {
|
||||
if (level.height) {
|
||||
return(level.height + 'p / ' + Math.round(level.bitrate / 1024) + 'kb');
|
||||
} else {
|
||||
return(Math.round(level.bitrate / 1024) + 'kb');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function _errorHandler(event : HLSEvent) : void {
|
||||
var errorCode : int = ErrorManager.getMediaErrorCode(event);
|
||||
var errorMsg : String = ErrorManager.getMediaErrorMessage(event);
|
||||
CONFIG::LOGGING {
|
||||
Log.warn("HLS Error event received, dispatching MediaError " + errorCode + "," + errorMsg);
|
||||
}
|
||||
updateLoadTrait(_loadTrait, LoadState.LOAD_ERROR);
|
||||
_loadTrait.dispatchEvent(new MediaErrorEvent(MediaErrorEvent.MEDIA_ERROR, false, false, new MediaError(errorCode, errorMsg)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
package org.mangui.osmf.plugins.loader {
|
||||
import flash.net.NetStream;
|
||||
import flash.net.NetConnection;
|
||||
|
||||
import org.osmf.net.NetLoader;
|
||||
import org.osmf.media.URLResource;
|
||||
import org.mangui.hls.HLS;
|
||||
|
||||
public class HLSNetLoader extends NetLoader {
|
||||
private var _hls : HLS;
|
||||
private var _connection : NetConnection;
|
||||
private var _resource : URLResource;
|
||||
|
||||
public function HLSNetLoader(hls : HLS) {
|
||||
_hls = hls;
|
||||
super();
|
||||
}
|
||||
|
||||
override protected function createNetStream(connection : NetConnection, resource : URLResource) : NetStream {
|
||||
_connection = connection;
|
||||
_resource = resource;
|
||||
return _hls.stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user