Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add maxSkippedFragments setting to define max skipped fragments before throwing an error #461

Merged
merged 3 commits into from
Dec 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ The plugin accepts several **optional** configuration options, such as:
- `hls_fragmentloadskipaftermaxretry` (default true): control behaviour in case fragment load still fails after max retry timeout
* true : fragment will be skipped and next one will be loaded.
* false : an I/O Error will be raised.
- `hls_maxskippedfragments` (default 5): Maximum count of skipped fragments in a row before an I/O Error will be raised.
* 0 - no skip (same as fragmentLoadSkipAfterMaxRetry = false).
* -1 - no limit for skipping, skip till the end of the playlist.
- `hls_capleveltostage` (default false) : limit levels usable in auto-quality by the stage dimensions (width and height)
- true : level width and height (defined in m3u8 playlist) will be compared with the player width and height (stage.stageWidth and stage.stageHeight). Max level will be set depending on the `hls_maxlevelcappingmode` option. Note: this setting is ignored in manual mode so all the levels could be selected manually.
- false : levels will not be limited. All available levels could be used in auto-quality mode taking only bandwidth into consideration.
Expand Down
11 changes: 11 additions & 0 deletions src/org/mangui/hls/HLSSettings.as
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,17 @@ package org.mangui.hls {
*/
public static var fragmentLoadSkipAfterMaxRetry : Boolean = true;

/**
* maxSkippedFragments
*
* Maximum count of skipped fragments in a row before an I/O Error will be raised.
* 0 - no skip (same as fragmentLoadSkipAfterMaxRetry = false)
* -1 - no limit for skipping, skip till the end of the playlist
*
* Default is 5.
*/
public static var maxSkippedFragments : int = 5;

/**
* flushLiveURLCache
*
Expand Down
32 changes: 23 additions & 9 deletions src/org/mangui/hls/loader/FragmentLoader.as
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ package org.mangui.hls.loader {
import flash.events.*;
import flash.net.*;
import flash.utils.ByteArray;
import flash.utils.getTimer;
import flash.utils.Timer;
import flash.utils.getTimer;

import org.mangui.hls.HLS;
import org.mangui.hls.HLSSettings;
import org.mangui.hls.constant.HLSLoaderTypes;
import org.mangui.hls.constant.HLSTypes;
import org.mangui.hls.controller.AudioTrackController;
import org.mangui.hls.controller.LevelController;
import org.mangui.hls.demux.Demuxer;
import org.mangui.hls.demux.DemuxHelper;
import org.mangui.hls.demux.Demuxer;
import org.mangui.hls.demux.ID3Tag;
import org.mangui.hls.event.HLSError;
import org.mangui.hls.event.HLSEvent;
import org.mangui.hls.event.HLSLoadMetrics;
import org.mangui.hls.flv.FLVTag;
import org.mangui.hls.HLS;
import org.mangui.hls.HLSSettings;
import org.mangui.hls.model.AudioTrack;
import org.mangui.hls.model.Fragment;
import org.mangui.hls.model.FragmentData;
Expand Down Expand Up @@ -81,6 +82,7 @@ package org.mangui.hls.loader {
private var _fragRetryCount : int;
private var _fragLoadStatus : int;
private var _fragSkipping : Boolean;
private var _fragSkipCount : int;
/** reference to previous/current fragment */
private var _fragPrevious : Fragment;
private var _fragCurrent : Fragment;
Expand Down Expand Up @@ -334,6 +336,7 @@ package org.mangui.hls.loader {
_fragmentFirstLoaded = false;
_fragPrevious = null;
_fragSkipping = false;
_fragSkipCount = 0;
_levelNext = -1;
_timer.start();
}
Expand All @@ -348,6 +351,7 @@ package org.mangui.hls.loader {
_loadingState = LOADING_IDLE;
_fragmentFirstLoaded = true;
_fragSkipping = false;
_fragSkipCount = 0;
_levelNext = -1;
_fragPrevious = lastFrag;
_timer.start();
Expand Down Expand Up @@ -447,7 +451,7 @@ package org.mangui.hls.loader {
}
// switch back to IDLE state to request new fragment at lowest level
_loadingState = LOADING_IDLE;
} else if(HLSSettings.fragmentLoadSkipAfterMaxRetry == true) {
} else if(HLSSettings.fragmentLoadSkipAfterMaxRetry == true && _fragSkipCount < HLSSettings.maxSkippedFragments || HLSSettings.maxSkippedFragments < 0) {
CONFIG::LOGGING {
Log.warn("error parsing fragment, skip it and load next one");
}
Expand All @@ -459,6 +463,10 @@ package org.mangui.hls.loader {
_fragRetryTimeout = 1000;
_fragPrevious = _fragCurrent;
_fragSkipping = true;
_fragSkipCount++;
CONFIG::LOGGING {
Log.debug("fragments skipped / max: " + _fragSkipCount + "/" + HLSSettings.maxSkippedFragments );
}
// set fragment first loaded to be true to ensure that we can skip first fragment as well
_fragmentFirstLoaded = true;
_loadingState = LOADING_IDLE;
Expand Down Expand Up @@ -512,7 +520,7 @@ package org.mangui.hls.loader {
}
// switch back to IDLE state to request new fragment at lowest level
_loadingState = LOADING_IDLE;
} else if(HLSSettings.fragmentLoadSkipAfterMaxRetry == true) {
} else if(HLSSettings.fragmentLoadSkipAfterMaxRetry == true && _fragSkipCount < HLSSettings.maxSkippedFragments || HLSSettings.maxSkippedFragments < 0) {
/* check if loaded fragment is not the last one of a live playlist.
if it is the case, don't skip to next, as there is no next fragment :-)
*/
Expand All @@ -527,7 +535,7 @@ package org.mangui.hls.loader {
_fragRetryTimeout = Math.min(HLSSettings.fragmentLoadMaxRetryTimeout, 2 * _fragRetryTimeout);
} else {
CONFIG::LOGGING {
Log.warn("max fragment load retry reached, skip fragment and load next one");
Log.warn("max fragment load retry reached, skip fragment and load next one.");
}
var tags : Vector.<FLVTag> = tags = new Vector.<FLVTag>();
tags.push(_fragCurrent.getSkippedTag());
Expand All @@ -537,6 +545,10 @@ package org.mangui.hls.loader {
_fragRetryTimeout = 1000;
_fragPrevious = _fragCurrent;
_fragSkipping = true;
_fragSkipCount++;
CONFIG::LOGGING {
Log.debug("fragments skipped / max: " + _fragSkipCount + "/" + HLSSettings.maxSkippedFragments );
}
// set fragment first loaded to be true to ensure that we can skip first fragment as well
_fragmentFirstLoaded = true;
_loadingState = LOADING_IDLE;
Expand Down Expand Up @@ -601,6 +613,7 @@ package org.mangui.hls.loader {
Log.debug("loading completed");
}
_fragSkipping = false;
_fragSkipCount = 0;
_metrics.loading_end_time = getTimer();
_metrics.size = fragData.bytesLoaded;

Expand Down Expand Up @@ -978,7 +991,7 @@ package org.mangui.hls.loader {

/* try to do progressive buffering here.
* only do it in case :
* first fragment is already loaded
* first fragment is already loaded
* or if first fragment is not loaded, we can do it if
* startLevel is already defined (startLevel is already set or
* startFromLevel/startFromBitrate not set to -1
Expand Down Expand Up @@ -1062,9 +1075,10 @@ package org.mangui.hls.loader {
_fragHandleParsingError("error parsing fragment, no tag found");
return;
}
// parsing complete, reset retry counter
// parsing complete, reset retry and skip counters
_fragRetryCount = 0;
_fragRetryTimeout = 1000;
_fragSkipCount = 0;
CONFIG::LOGGING {
if (fragData.audio_found) {
Log.debug("m/M audio PTS:" + fragData.pts_min_audio + "/" + fragData.pts_max_audio);
Expand Down