no commit message

This commit is contained in:
niandeng
2020-09-17 18:40:01 +08:00
parent 4382915d09
commit d957abceaa
283 changed files with 86935 additions and 63 deletions
@@ -0,0 +1,119 @@
/* 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.traits {
import org.mangui.hls.HLS;
import org.mangui.hls.model.AudioTrack;
import org.mangui.hls.event.HLSEvent;
import org.osmf.events.AlternativeAudioEvent;
import org.osmf.media.MediaElement;
import org.osmf.net.StreamingItem;
import org.osmf.traits.AlternativeAudioTrait;
import org.osmf.utils.OSMFStrings;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSAlternativeAudioTrait extends AlternativeAudioTrait {
private var _hls : HLS;
private var _media : MediaElement;
private var _audioTrackList : Vector.<AudioTrack>;
private var _numAlternativeAudioStreams : int;
private var _activeTransitionIndex : int = DEFAULT_TRANSITION_INDEX;
private var _lastTransitionIndex : int = INVALID_TRANSITION_INDEX;
public function HLSAlternativeAudioTrait(hls : HLS, media : MediaElement) {
CONFIG::LOGGING {
Log.debug("HLSAlternativeAudioTrait()");
}
_hls = hls;
_audioTrackList = _hls.audioTracks;
_numAlternativeAudioStreams = _audioTrackList.length - 1;
super(_numAlternativeAudioStreams);
_media = media;
_hls.addEventListener(HLSEvent.AUDIO_TRACK_SWITCH, _audioTrackChangedHandler);
_hls.addEventListener(HLSEvent.AUDIO_TRACKS_LIST_CHANGE, _audioTrackListChangedHandler);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSAlternativeAudioTrait:dispose");
}
_hls.removeEventListener(HLSEvent.AUDIO_TRACK_SWITCH, _audioTrackChangedHandler);
_hls.removeEventListener(HLSEvent.AUDIO_TRACKS_LIST_CHANGE, _audioTrackListChangedHandler);
super.dispose();
}
override public function get numAlternativeAudioStreams() : int {
CONFIG::LOGGING {
Log.debug("HLSAlternativeAudioTrait:numAlternativeAudioStreams:" + _numAlternativeAudioStreams);
}
return _numAlternativeAudioStreams;
}
override public function getItemForIndex(index : int) : StreamingItem {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:getItemForIndex(" + index + ")");
}
if (index <= INVALID_TRANSITION_INDEX || index >= numAlternativeAudioStreams) {
throw new RangeError(OSMFStrings.getString(OSMFStrings.ALTERNATIVEAUDIO_INVALID_INDEX));
}
if (index == DEFAULT_TRANSITION_INDEX) {
return null;
}
var name : String = _audioTrackList[index + 1].title;
var streamItem : StreamingItem = new StreamingItem("AUDIO", name);
streamItem.info.label = name;
return streamItem;
}
override protected function endSwitching(index : int) : void {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:endSwitching(" + index + ")");
}
if (switching) {
executeSwitching(_indexToSwitchTo);
}
super.endSwitching(index);
}
protected function executeSwitching(indexToSwitchTo : int) : void {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:executeSwitching(" + indexToSwitchTo + ")");
}
if (_lastTransitionIndex != indexToSwitchTo) {
_activeTransitionIndex = indexToSwitchTo;
_hls.audioTrack = indexToSwitchTo + 1;
}
}
private function _audioTrackChangedHandler(event : HLSEvent) : void {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:_audioTrackChangedHandler");
}
setSwitching(false, _activeTransitionIndex);
_lastTransitionIndex = _activeTransitionIndex;
}
private function _audioTrackListChangedHandler(event : HLSEvent) : void {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:_audioTrackListChangedHandler");
}
_audioTrackList = _hls.audioTracks;
if (_audioTrackList.length > 0) {
// try to change default Audio Track Title for GrindPlayer ...
if (_audioTrackList[0].title.indexOf("TS/") == -1) {
CONFIG::LOGGING {
Log.debug("default audio track title:" + _audioTrackList[0].title);
}
_media.resource.addMetadataValue("defaultAudioLabel", _audioTrackList[0].title);
}
}
_numAlternativeAudioStreams = _audioTrackList.length - 1;
if (_numAlternativeAudioStreams > 0) {
dispatchEvent(new AlternativeAudioEvent(AlternativeAudioEvent.NUM_ALTERNATIVE_AUDIO_STREAMS_CHANGE, false, false, false));
}
}
}
}
@@ -0,0 +1,57 @@
/* 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.traits {
import org.mangui.hls.HLS;
import org.mangui.hls.event.HLSEvent;
import org.mangui.hls.constant.HLSPlayStates;
import org.osmf.traits.BufferTrait;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSBufferTrait extends BufferTrait {
private var _hls : HLS;
public function HLSBufferTrait(hls : HLS) {
CONFIG::LOGGING {
Log.debug("HLSBufferTrait()");
}
super();
_hls = hls;
_hls.addEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSBufferTrait:dispose");
}
_hls.removeEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler);
super.dispose();
}
override public function get bufferLength() : Number {
return _hls.stream.bufferLength;
}
/** state changed handler **/
private function _stateChangedHandler(event : HLSEvent) : void {
switch(event.state) {
case HLSPlayStates.PLAYING_BUFFERING:
case HLSPlayStates.PAUSED_BUFFERING:
CONFIG::LOGGING {
Log.debug("HLSBufferTrait:_stateChangedHandler:setBuffering(true)");
}
setBuffering(true);
break;
default:
CONFIG::LOGGING {
Log.debug("HLSBufferTrait:_stateChangedHandler:setBuffering(false)");
}
setBuffering(false);
break;
}
}
}
}
@@ -0,0 +1,9 @@
package org.mangui.osmf.plugins.traits
{
public final class HLSClosedCaptionsState
{
public static const YES:String = "yes";
public static const NO:String = "no";
public static const UNKNOWN:String = "unknown";
}
}
@@ -0,0 +1,58 @@
/* 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.traits {
import org.mangui.hls.HLS;
import org.mangui.hls.event.HLSEvent;
import org.mangui.hls.model.Level;
import org.osmf.traits.MediaTraitBase;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSClosedCaptionsTrait extends MediaTraitBase {
private var _hls : HLS;
private var _hasClosedCapations : String;
public function HLSClosedCaptionsTrait(hls : HLS, closed_captions : String = HLSClosedCaptionsState.UNKNOWN) {
CONFIG::LOGGING {
Log.debug("HLSClosedCaptionsTrait()");
}
super(HLSMediaTraitType.CLOSED_CAPTIONS);
_hasClosedCapations = closed_captions;
_hls = hls;
_hls.addEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSClosedCaptionsTrait:dispose");
}
_hls.removeEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
super.dispose();
}
public function hasClosedCaptions() : String {
return _hasClosedCapations;
}
/** Update playback position/duration **/
private function _levelSwitchHandler(event : HLSEvent) : void {
var cc : String = (_hls.levels[event.level] as Level).closed_captions;
if (cc && cc === "NONE")
{
// manifest told us to ignore any 608/708 binary
_hasClosedCapations = HLSClosedCaptionsState.NO;
}
else
{
_hasClosedCapations = HLSClosedCaptionsState.UNKNOWN;
}
// YES only happens for WebVTT, which isn't supported.
}
}
}
@@ -0,0 +1,65 @@
/* 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.traits {
import flash.display.DisplayObject;
import flash.display.Stage;
import flash.events.Event;
import org.mangui.hls.HLS;
import org.osmf.media.videoClasses.VideoSurface;
import org.osmf.traits.DisplayObjectTrait;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSDisplayObjectTrait extends DisplayObjectTrait {
private var videoSurface : VideoSurface;
private var _hls : HLS;
public function HLSDisplayObjectTrait(hls : HLS, videoSurface : DisplayObject, mediaWidth : int = 0, mediaHeight : int = 0) {
CONFIG::LOGGING {
Log.debug("HLSDisplayObjectTrait()");
}
_hls = hls;
super(videoSurface, mediaWidth, mediaHeight);
this.videoSurface = videoSurface as VideoSurface;
if (this.videoSurface is VideoSurface)
this.videoSurface.addEventListener(Event.ADDED_TO_STAGE, onStage);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSDisplayObjectTrait:dispose");
}
videoSurface.removeEventListener(Event.ENTER_FRAME, onFrame);
super.dispose();
}
private function onStage(event : Event) : void {
_hls.stage = event.target.stage as Stage;
videoSurface.removeEventListener(Event.ADDED_TO_STAGE, onStage);
videoSurface.addEventListener(Event.ENTER_FRAME, onFrame);
}
private function onFrame(event : Event) : void {
var newWidth : int = videoSurface.videoWidth;
var newHeight : int = videoSurface.videoHeight;
if (newWidth != 0 && newHeight != 0 && (newWidth != mediaWidth || newHeight != mediaHeight)) {
// If there is no layout, set as no scale.
if (videoSurface.width == 0 && videoSurface.height == 0) {
videoSurface.width = newWidth;
videoSurface.height = newHeight;
}
CONFIG::LOGGING {
Log.info("HLSDisplayObjectTrait:setMediaSize(" + newWidth + "," + newHeight + ")");
}
setMediaSize(newWidth, newHeight);
}
// videoSurface.removeEventListener(Event.ENTER_FRAME, onFrame);
}
}
}
@@ -0,0 +1,86 @@
/* 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.traits {
import org.mangui.hls.HLS;
import org.mangui.hls.event.HLSEvent;
import org.osmf.traits.DynamicStreamTrait;
import org.osmf.utils.OSMFStrings;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSDynamicStreamTrait extends DynamicStreamTrait {
private var _hls : HLS;
public function HLSDynamicStreamTrait(hls : HLS) {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait()");
}
_hls = hls;
_hls.addEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
super(true, _hls.startLevel, hls.levels.length);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:dispose");
}
_hls.removeEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
super.dispose();
}
override public function getBitrateForIndex(index : int) : Number {
if (index > numDynamicStreams - 1 || index < 0) {
throw new RangeError(OSMFStrings.getString(OSMFStrings.STREAMSWITCH_INVALID_INDEX));
}
var bitrate : Number = _hls.levels[index].bitrate / 1000;
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:getBitrateForIndex(" + index + ")=" + bitrate);
}
return bitrate;
}
override public function switchTo(index : int) : void {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:switchTo(" + index + ")/max:" + maxAllowedIndex);
}
if (index < 0 || index > maxAllowedIndex) {
throw new RangeError(OSMFStrings.getString(OSMFStrings.STREAMSWITCH_INVALID_INDEX));
}
autoSwitch = false;
if (!switching) {
setSwitching(true, index);
}
}
override protected function autoSwitchChangeStart(value : Boolean) : void {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:autoSwitchChangeStart:" + value);
}
if (value == true && _hls.autoLevel == false) {
_hls.nextLevel = -1;
}
}
override protected function switchingChangeStart(newSwitching : Boolean, index : int) : void {
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:switchingChangeStart(newSwitching/index):" + newSwitching + "/" + index);
}
if (newSwitching) {
_hls.currentLevel = index;
}
}
/** Update playback position/duration **/
private function _levelSwitchHandler(event : HLSEvent) : void {
var newLevel : int = event.level;
CONFIG::LOGGING {
Log.debug("HLSDynamicStreamTrait:_qualitySwitchHandler:" + newLevel);
}
setCurrentIndex(newLevel);
setSwitching(false, newLevel);
};
}
}
@@ -0,0 +1,7 @@
package org.mangui.osmf.plugins.traits
{
public final class HLSMediaTraitType
{
public static const CLOSED_CAPTIONS:String = "hlsClosedCaptions";
}
}
@@ -0,0 +1,71 @@
/* 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.traits {
import org.mangui.hls.HLS;
import org.mangui.hls.event.HLSEvent;
import org.osmf.media.MediaResourceBase;
import org.osmf.net.NetStreamLoadTrait;
import org.osmf.traits.LoaderBase;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSNetStreamLoadTrait extends NetStreamLoadTrait {
private var _hls : HLS;
private var _timeLoaded : Number;
private var _timeTotal : Number;
public function HLSNetStreamLoadTrait(hls : HLS, duration : Number, loader : LoaderBase, resource : MediaResourceBase) {
CONFIG::LOGGING {
Log.debug("HLSNetStreamLoadTrait()");
}
super(loader, resource);
_hls = hls;
_timeLoaded = 0;
_timeTotal = duration;
super.netStream = _hls.stream;
_hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSNetStreamLoadTrait:dispose");
}
_hls.removeEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
super.dispose();
}
override public function get bytesLoaded() : Number {
return _timeLoaded;
}
override public function get bytesTotal() : Number {
return _timeTotal;
}
public function get hls() : HLS {
return _hls;
}
/** **/
private function _mediaTimeHandler(event : HLSEvent) : void {
var timeTotal : Number = Math.round(10 * event.mediatime.duration) / 10;
var timeLoaded : Number = Math.max(0,Math.round(10 * (event.mediatime.position + event.mediatime.buffer)) / 10);
if (_timeTotal != timeTotal) {
if (timeTotal < _timeLoaded || timeTotal < 0) {
timeTotal = NaN;
}
_timeTotal = timeTotal;
setBytesTotal(timeTotal);
}
if (_timeLoaded != timeLoaded && timeLoaded <= timeTotal) {
_timeLoaded = timeLoaded;
setBytesLoaded(timeLoaded);
}
};
}
}
@@ -0,0 +1,82 @@
/* 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.traits {
import org.mangui.hls.HLS;
import org.mangui.hls.constant.HLSPlayStates;
import org.mangui.hls.event.HLSEvent;
import org.osmf.traits.PlayState;
import org.osmf.traits.PlayTrait;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSPlayTrait extends PlayTrait {
private var _hls : HLS;
private var streamStarted : Boolean = false;
public function HLSPlayTrait(hls : HLS) {
CONFIG::LOGGING {
Log.debug("HLSPlayTrait()");
}
super();
_hls = hls;
_hls.addEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler);
_hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSPlayTrait:dispose");
}
_hls.removeEventListener(HLSEvent.PLAYBACK_STATE, _stateChangedHandler);
_hls.removeEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete);
super.dispose();
}
override protected function playStateChangeStart(newPlayState:String):void {
CONFIG::LOGGING {
Log.info("HLSPlayTrait:playStateChangeStart:" + newPlayState);
}
switch (newPlayState) {
case PlayState.PLAYING:
if (!streamStarted) {
_hls.stream.play();
streamStarted = true;
}
else {
_hls.stream.resume();
}
break;
case PlayState.PAUSED:
_hls.stream.pause();
break;
case PlayState.STOPPED:
streamStarted = false;
_hls.stream.close();
break;
}
}
/** state changed handler **/
private function _stateChangedHandler(event:HLSEvent):void {
switch (event.state) {
case HLSPlayStates.PLAYING:
CONFIG::LOGGING {
Log.debug("HLSPlayTrait:_stateChangedHandler:setBuffering(true)");
}
if (!streamStarted) {
streamStarted = true;
play();
}
default:
}
}
/** playback complete handler **/
private function _playbackComplete(event : HLSEvent) : void {
stop();
}
}
}
@@ -0,0 +1,61 @@
/* 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.traits {
import org.mangui.hls.HLS;
import org.mangui.hls.event.HLSEvent;
import org.mangui.hls.constant.HLSSeekStates;
import org.osmf.traits.SeekTrait;
import org.osmf.traits.TimeTrait;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSSeekTrait extends SeekTrait {
private var _hls : HLS;
public function HLSSeekTrait(hls : HLS, timeTrait : TimeTrait) {
CONFIG::LOGGING {
Log.debug("HLSSeekTrait()");
}
super(timeTrait);
_hls = hls;
_hls.addEventListener(HLSEvent.SEEK_STATE, _stateChangedHandler);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSSeekTrait:dispose");
}
_hls.removeEventListener(HLSEvent.SEEK_STATE, _stateChangedHandler);
super.dispose();
}
/**
* @private
* Communicates a <code>seeking</code> change to the media through the NetStream.
* @param newSeeking New <code>seeking</code> value.
* @param time Time to seek to, in seconds.
*/
override protected function seekingChangeStart(newSeeking : Boolean, time : Number) : void {
if (newSeeking) {
CONFIG::LOGGING {
Log.info("HLSSeekTrait:seekingChangeStart(newSeeking/time):(" + newSeeking + "/" + time + ")");
}
_hls.stream.seek(time);
}
super.seekingChangeStart(newSeeking, time);
}
/** state changed handler **/
private function _stateChangedHandler(event : HLSEvent) : void {
if (seeking && event.state != HLSSeekStates.SEEKING) {
CONFIG::LOGGING {
Log.debug("HLSSeekTrait:setSeeking(false);");
}
setSeeking(false, timeTrait.currentTime);
}
}
}
}
@@ -0,0 +1,60 @@
/* 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.traits {
import org.mangui.hls.HLS;
import org.mangui.hls.constant.HLSTypes;
import org.mangui.hls.event.HLSEvent;
import org.osmf.traits.TimeTrait;
import org.osmf.events.TimeEvent;
CONFIG::LOGGING {
import org.mangui.hls.utils.Log;
}
public class HLSTimeTrait extends TimeTrait {
private var _hls : HLS;
public function HLSTimeTrait(hls : HLS, duration : Number = 0) {
CONFIG::LOGGING {
Log.debug("HLSTimeTrait()");
}
super(duration);
setCurrentTime(0);
_hls = hls;
_hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
_hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete);
}
override public function dispose() : void {
CONFIG::LOGGING {
Log.debug("HLSTimeTrait:dispose");
}
_hls.removeEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
_hls.removeEventListener(HLSEvent.PLAYBACK_COMPLETE, _playbackComplete);
super.dispose();
}
override protected function signalComplete():void
{
// live streams shouldn't end based on TimeTrait
if (_hls.type !== HLSTypes.LIVE)
{
dispatchEvent(new TimeEvent(TimeEvent.COMPLETE));
}
}
/** Update playback position/duration **/
private function _mediaTimeHandler(event : HLSEvent) : void {
var newDuration : Number = event.mediatime.duration;
var newPosition : Number = Math.max(0, event.mediatime.position);
setDuration(newDuration);
setCurrentTime(newPosition);
};
/** playback complete handler **/
private function _playbackComplete(event : HLSEvent) : void {
signalComplete();
}
}
}