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

feat(DASH): Add initial support for "urn:mpeg:dash:ssr:2023" #5762

Merged
merged 31 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
babed53
feat(DASH): Add initial support to urn:mpeg:dash:ssr:2023
avelad Oct 11, 2023
ccfe9d3
Merge branch 'main' into segment-sequence-representation
avelad Oct 11, 2023
a46b3b2
feat(DASH): Add initial support to urn:mpeg:dash:ssr:2023
avelad Oct 11, 2023
57d3031
feat(DASH): Add initial support to urn:mpeg:dash:ssr:2023
avelad Oct 11, 2023
2e9180b
Merge branch 'main' into segment-sequence-representation
avelad Oct 12, 2023
85e14dd
Merge branch 'main' into segment-sequence-representation
avelad Oct 23, 2023
343038e
feat(DASH): Add initial support to urn:mpeg:dash:ssr:2023
avelad Oct 23, 2023
4bee6cb
feat(DASH): Add initial support for urn:mpeg:dash:ssr:2023
avelad Oct 23, 2023
a712da4
feat(DASH): Add initial support for urn:mpeg:dash:ssr:2023
avelad Oct 23, 2023
bf89da2
fix: Fix chooseCodecsAndFilterManifest for some HLS manifest
avelad Oct 24, 2023
ba4ff98
Merge branch 'hls-variants-filtering' into segment-sequence-represent…
avelad Oct 24, 2023
066f349
feat(DASH): Add initial support for urn:mpeg:dash:ssr:2023
avelad Oct 24, 2023
fa7ede6
Merge branch 'main' into segment-sequence-representation
avelad Oct 24, 2023
0d1ca5d
Merge branch 'main' into segment-sequence-representation
avelad Oct 26, 2023
f7b2dc7
feat: Improve latency in LL DASH streams
avelad Oct 27, 2023
09826f4
Merge branch 'prefecth-low-latency' into segment-sequence-representation
avelad Oct 27, 2023
f9755b1
Merge branch 'main' into segment-sequence-representation
avelad Oct 27, 2023
3557c08
feat: Add partial info to shaka.media.SegmentReference
avelad Oct 27, 2023
020f6cf
Merge branch 'partial-info-segment-reference' into segment-sequence-r…
avelad Oct 27, 2023
f855bf1
feat: Allow prefetch init segments
avelad Oct 27, 2023
7f526bb
Merge branch 'prefetch-init-segments' into segment-sequence-represent…
avelad Oct 27, 2023
b03474d
Merge branch 'main' into segment-sequence-representation
avelad Oct 30, 2023
dba1914
feat(DASH): Add initial support for urn:mpeg:dash:ssr:2023
avelad Oct 30, 2023
ea4dd4b
feat(DASH): Add initial support for urn:mpeg:dash:ssr:2023
avelad Oct 30, 2023
6212c1a
Merge branch 'main' into segment-sequence-representation
avelad Oct 30, 2023
d7522c7
Merge branch 'main' into segment-sequence-representation
avelad Oct 31, 2023
ff5c421
Merge branch 'main' into segment-sequence-representation
avelad Oct 31, 2023
26ee42f
Merge branch 'main' into segment-sequence-representation
avelad Oct 31, 2023
3ef53aa
Merge branch 'main' into segment-sequence-representation
avelad Nov 2, 2023
9237d1f
Fix review
avelad Nov 2, 2023
494e2fb
Add comment
avelad Nov 2, 2023
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
8 changes: 6 additions & 2 deletions externs/shaka/abr_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ shaka.extern.AbrManager = class {

/**
* Chooses one variant to switch to. Called by the Player.
* @param {boolean=} preferFastSwitching If not provided meant "avoid fast
* switching if possible".
* @return {shaka.extern.Variant}
* @exportDoc
*/
chooseVariant() {}
chooseVariant(preferFastSwitching) {}

/**
* Enables automatic Variant choices from the last ones passed to setVariants.
Expand All @@ -88,9 +90,11 @@ shaka.extern.AbrManager = class {
* @param {number} deltaTimeMs The duration, in milliseconds, that the request
* took to complete.
* @param {number} numBytes The total number of bytes transferred.
* @param {boolean} allowSwitch Indicate if the segment is allowed to switch
* to another stream.
* @exportDoc
*/
segmentDownloaded(deltaTimeMs, numBytes) {}
segmentDownloaded(deltaTimeMs, numBytes, allowSwitch) {}

/**
* Gets an estimate of the current bandwidth in bit/sec. This is used by the
Expand Down
5 changes: 4 additions & 1 deletion externs/shaka/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,8 @@ shaka.extern.FetchCryptoKeysFunction;
* (!Array.<shaka.extern.Stream>|!Array.<shaka.extern.StreamDB>|
* undefined),
* mssPrivateData: (shaka.extern.MssPrivateData|undefined),
* external: boolean
* external: boolean,
* fastSwitching: boolean
* }}
*
* @description
Expand Down Expand Up @@ -524,6 +525,8 @@ shaka.extern.FetchCryptoKeysFunction;
* @property {boolean} external
* Indicate if the stream was added externally.
* Eg: external text tracks.
* @property {boolean} fastSwitching
* Indicate if the stream should be used for fast switching.
*
* @exportDoc
*/
Expand Down
5 changes: 4 additions & 1 deletion externs/shaka/offline.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ shaka.extern.ManifestDB;
* spatialAudio: boolean,
* closedCaptions: Map.<string, string>,
* tilesLayout: (string|undefined),
* external: boolean
* external: boolean,
* fastSwitching: boolean
* }}
*
* @property {number} id
Expand Down Expand Up @@ -212,6 +213,8 @@ shaka.extern.ManifestDB;
* @property {boolean} external
* Indicate if the stream was added externally.
* Eg: external text tracks.
* @property {boolean} fastSwitching
* Indicate if the stream should be used for fast switching.
*/
shaka.extern.StreamDB;

Expand Down
31 changes: 24 additions & 7 deletions lib/abr/simple_abr_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,12 @@ shaka.abr.SimpleAbrManager = class {


/**
* @param {boolean=} preferFastSwitching
avelad marked this conversation as resolved.
Show resolved Hide resolved
* @return {shaka.extern.Variant}
* @override
* @export
*/
chooseVariant() {
chooseVariant(preferFastSwitching = false) {
const SimpleAbrManager = shaka.abr.SimpleAbrManager;

let maxHeight = Infinity;
Expand All @@ -190,9 +192,24 @@ shaka.abr.SimpleAbrManager = class {
maxWidth, this.mediaElement_.clientWidth * devicePixelRatio);
}

let normalVariants = this.variants_.filter((variant) => {
return !shaka.util.StreamUtils.isFastSwitching(variant);
});
if (!normalVariants.length) {
normalVariants = this.variants_;
}

let variants = normalVariants;
if (preferFastSwitching &&
normalVariants.length != this.variants_.length) {
variants = this.variants_.filter((variant) => {
return shaka.util.StreamUtils.isFastSwitching(variant);
});
}

// Get sorted Variants.
let sortedVariants = SimpleAbrManager.filterAndSortVariants_(
this.config_.restrictions, this.variants_,
this.config_.restrictions, variants,
/* maxHeight= */ Infinity, /* maxWidth= */ Infinity);

if (maxHeight != Infinity || maxWidth != Infinity) {
Expand All @@ -206,14 +223,14 @@ shaka.abr.SimpleAbrManager = class {
}

sortedVariants = SimpleAbrManager.filterAndSortVariants_(
this.config_.restrictions, this.variants_, maxHeight, maxWidth);
this.config_.restrictions, variants, maxHeight, maxWidth);
}

const defaultBandwidthEstimate = this.getDefaultBandwidth_();
const currentBandwidth = this.bandwidthEstimator_.getBandwidthEstimate(
defaultBandwidthEstimate);

if (this.variants_.length && !sortedVariants.length) {
if (variants.length && !sortedVariants.length) {
// If we couldn't meet the ABR restrictions, we should still play
// something.
// These restrictions are not "hard" restrictions in the way that
Expand All @@ -222,7 +239,7 @@ shaka.abr.SimpleAbrManager = class {
shaka.log.warning('No variants met the ABR restrictions. ' +
'Choosing a variant by lowest bandwidth.');
sortedVariants = SimpleAbrManager.filterAndSortVariants_(
/* restrictions= */ null, this.variants_,
/* restrictions= */ null, variants,
/* maxHeight= */ Infinity, /* maxWidth= */ Infinity);
sortedVariants = [sortedVariants[0]];
}
Expand Down Expand Up @@ -285,7 +302,7 @@ shaka.abr.SimpleAbrManager = class {
* @override
* @export
*/
segmentDownloaded(deltaTimeMs, numBytes) {
segmentDownloaded(deltaTimeMs, numBytes, allowSwitch) {
shaka.log.v2('Segment downloaded:',
'deltaTimeMs=' + deltaTimeMs,
'numBytes=' + numBytes,
Expand All @@ -294,7 +311,7 @@ shaka.abr.SimpleAbrManager = class {
goog.asserts.assert(deltaTimeMs >= 0, 'expected a non-negative duration');
this.bandwidthEstimator_.sample(deltaTimeMs, numBytes);

if ((this.lastTimeChosenMs_ != null) && this.enabled_) {
if (allowSwitch && (this.lastTimeChosenMs_ != null) && this.enabled_) {
this.suggestStreams_();
}
}
Expand Down
25 changes: 24 additions & 1 deletion lib/dash/dash_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,7 @@ shaka.dash.DashParser = class {
XmlUtils.findChildren(elem, 'EssentialProperty');
// ID of real AdaptationSet if this is a trick mode set:
let trickModeFor = null;
let isFastSwitching = false;
let unrecognizedEssentialProperty = false;
for (const prop of essentialProperties) {
const schemeId = prop.getAttribute('schemeIdUri');
Expand All @@ -1004,6 +1005,8 @@ shaka.dash.DashParser = class {
} else if (schemeId == colourPrimariesScheme ||
schemeId == matrixCoefficientsScheme) {
continue;
} else if (schemeId == 'urn:mpeg:dash:ssr:2023') {
isFastSwitching = true;
} else {
unrecognizedEssentialProperty = true;
}
Expand Down Expand Up @@ -1161,6 +1164,7 @@ shaka.dash.DashParser = class {
closedCaptions, representation, accessibilityPurpose);
if (parsedRepresentation) {
parsedRepresentation.hdr = parsedRepresentation.hdr || videoRange;
parsedRepresentation.fastSwitching = isFastSwitching;
}
return parsedRepresentation;
}).filter((s) => !!s);
Expand Down Expand Up @@ -1475,6 +1479,7 @@ shaka.dash.DashParser = class {
matchedStreams: [],
accessibilityPurpose,
external: false,
fastSwitching: false,
};
}

Expand Down Expand Up @@ -1585,6 +1590,7 @@ shaka.dash.DashParser = class {
numChannels: null,
audioSamplingRate: null,
availabilityTimeOffset: 0,
segmentSequenceCadence: 0,
});
getBaseUris = getBaseUris || parent.getBaseUris;

Expand Down Expand Up @@ -1635,6 +1641,17 @@ shaka.dash.DashParser = class {
const availabilityTimeOffset = parent.availabilityTimeOffset + baseUriAto +
segmentBaseAto + segmentTemplateAto;

let segmentSequenceCadence = null;
const segmentSequenceProperties =
XmlUtils.findChild(elem, 'SegmentSequenceProperties');
if (segmentSequenceProperties) {
const sap = XmlUtils.findChild(segmentSequenceProperties, 'SAP');
if (sap) {
segmentSequenceCadence = XmlUtils.parseAttr(sap, 'cadence',
XmlUtils.parseInt);
}
}

return {
getBaseUris: () => ManifestParserUtils.resolveUris(getBaseUris(), uris),
segmentBase: segmentBase || parent.segmentBase,
Expand All @@ -1654,6 +1671,8 @@ shaka.dash.DashParser = class {
numChannels: numChannels,
audioSamplingRate: audioSamplingRate,
availabilityTimeOffset: availabilityTimeOffset,
segmentSequenceCadence:
segmentSequenceCadence || parent.segmentSequenceCadence,
};
}

Expand Down Expand Up @@ -2080,7 +2099,8 @@ shaka.dash.DashParser.RequestSegmentCallback;
* language: ?string,
* numChannels: ?number,
* audioSamplingRate: ?number,
* availabilityTimeOffset: number
* availabilityTimeOffset: number,
* segmentSequenceCadence: number
* }}
*
* @description
Expand Down Expand Up @@ -2121,6 +2141,9 @@ shaka.dash.DashParser.RequestSegmentCallback;
* Specifies the maximum sampling rate of the content, or null if unknown.
* @property {number} availabilityTimeOffset
* Specifies the total availabilityTimeOffset of the segment, or 0 if unknown.
* @property {number} segmentSequenceCadence
* Specifies the cadence of independent segments in Segment Sequence
* Representation.
*/
shaka.dash.DashParser.InheritanceFrame;

Expand Down
11 changes: 9 additions & 2 deletions lib/dash/mpd_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,24 @@ shaka.dash.MpdUtils = class {
* @param {string} uriTemplate
* @param {?string} representationId
* @param {?number} number
* @param {?number} subNumber
* @param {?number} bandwidth
* @param {?(number|bigint)} time
* @return {string} A URI string.
* @see ISO/IEC 23009-1:2014 section 5.3.9.4.4
*/
static fillUriTemplate(
uriTemplate, representationId, number, bandwidth, time) {
uriTemplate, representationId, number, subNumber, bandwidth, time) {
/** @type {!Object.<string, ?number|?string>} */
const valueTable = {
'RepresentationID': representationId,
'Number': number,
'SubNumber': subNumber,
'Bandwidth': bandwidth,
'Time': time,
};

const re = /\$(RepresentationID|Number|Bandwidth|Time)?(?:%0([0-9]+)([diouxX]))?\$/g; // eslint-disable-line max-len
const re = /\$(RepresentationID|Number|SubNumber|Bandwidth|Time)?(?:%0([0-9]+)([diouxX]))?\$/g; // eslint-disable-line max-len
const uri = uriTemplate.replace(re, (match, name, widthStr, format) => {
if (match == '$$') {
return '$';
Expand Down Expand Up @@ -154,6 +156,10 @@ shaka.dash.MpdUtils = class {
XmlUtils.parseAttr(timePoint, 'd', XmlUtils.parseNonNegativeInt);
const r = XmlUtils.parseAttr(timePoint, 'r', XmlUtils.parseInt);

const k = XmlUtils.parseAttr(timePoint, 'k', XmlUtils.parseInt);

const partialSegments = k || 0;

// Adjust the start time to account for the presentation time offset.
if (t != null) {
t -= unscaledPresentationTimeOffset;
Expand Down Expand Up @@ -236,6 +242,7 @@ shaka.dash.MpdUtils = class {
start: startTime / timescale,
end: endTime / timescale,
unscaledStart: startTime,
partialSegments: partialSegments,
};
timeline.push(item);

Expand Down
Loading
Loading