Skip to content

Commit

Permalink
Merge branch 'development' of https://github.com/Dash-Industry-Forum/…
Browse files Browse the repository at this point in the history
…dash.js into update/index.d.ts
  • Loading branch information
ShikiSeiren committed Jan 9, 2025
2 parents dc28e6b + 0d62e13 commit 778b0a3
Show file tree
Hide file tree
Showing 24 changed files with 290 additions and 53 deletions.
10 changes: 10 additions & 0 deletions samples/dash-if-reference-player/app/sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,16 @@
}
}
},
{
"name": "Livesim 2 DRM EZDRM-2-keys-cbcs",
"url": "https://livesim2.dashif.org/livesim2/drm_EZDRM-2-keys-cbcs/testpic_2s/Manifest.mpd",
"provider": "dashif"
},
{
"name": "Livesim 2 DRM EZDRM-1-key-cbcs",
"url": "https://livesim2.dashif.org/livesim2/drm_EZDRM-1-key-cbcs/testpic_2s/Manifest.mpd",
"provider": "dashif"
},
{
"name": "Livesim 2 ECCP with CBCS encryption and dashif:Laurl",
"url": "https://livesim2.dashif.org/livesim2/eccp_cbcs/testpic_2s/Manifest.mpd",
Expand Down
4 changes: 2 additions & 2 deletions samples/drm/clearkey.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
<div class="h-100 p-5 bg-light border rounded-3">
<h3>Clearkey DRM instantiation example</h3>
<p>This example shows how to use dash.js to play streams with Clearkey DRM protection. </p><p>For a detailed explanation on DRM playback in dash.js checkout the
<a href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Digital-Rights-Management-(DRM)-and-license-acquisition"
target="_blank">Wiki</a>.</p>
<a href="https://dashif.org/dash.js/pages/usage/drm.html"
target="_blank">documentation</a>.</p>
</div>
</div>
<div class="col-md-8">
Expand Down
4 changes: 2 additions & 2 deletions samples/drm/keepProtectionKeys.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ <h3>DRM - Keep MediaKeySession</h3>
the first playback attempt license requests will be visible. For any subsequent playback attempt
the existing MediaKeySession is reused and no additional license requests are performed.</p>
<p>For a detailed explanation on DRM playback in dash.js checkout the
<a href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Digital-Rights-Management-(DRM)-and-license-acquisition"
target="_blank">Wiki</a>.</p>
<a href="https://dashif.org/dash.js/pages/usage/drm.html"
target="_blank">documentation</a>.</p>
</div>
</div>
<div class="col-md-8">
Expand Down
4 changes: 2 additions & 2 deletions samples/drm/license-wrapping.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ <h3>License wrapping example</h3>
<p>This example shows how to use dash.js to modify the license request and the license
repsonse. </p>
<p>For a detailed explanation on DRM playback in dash.js checkout the
<a href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Digital-Rights-Management-(DRM)-and-license-acquisition"
target="_blank">Wiki</a>.</p>
<a href="https://dashif.org/dash.js/pages/usage/drm.html"
target="_blank">documentation</a>.</p>
</div>
</div>
<div class="col-md-8">
Expand Down
4 changes: 2 additions & 2 deletions samples/drm/playready.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@
<div class="h-100 p-5 bg-light border rounded-3">
<h3>PlayReady DRM instantiation example</h3>
<p>This example shows how to use dash.js to play streams with PlayReady DRM protection. </p><p>For a detailed explanation on DRM playback in dash.js checkout the
<a href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Digital-Rights-Management-(DRM)-and-license-acquisition"
target="_blank">Wiki</a>.</p>
<a href="https://dashif.org/dash.js/pages/usage/drm.html"
target="_blank">documentation</a>.</p>
</div>
</div>
<div class="col-md-8">
Expand Down
4 changes: 2 additions & 2 deletions samples/drm/robustness-level.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ <h3>DRM Robustness level example</h3>
<p>This example shows how to define a robustness level to be used by dash.js in the <i>requestMediaKeySystemAccess</i>
call. </p>
<p>For a detailed explanation on DRM playback in dash.js checkout the
<a href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Digital-Rights-Management-(DRM)-and-license-acquisition"
target="_blank">Wiki</a>.</p>
<a href="https://dashif.org/dash.js/pages/usage/drm.html"
target="_blank">documentation</a>.</p>
</div>
</div>
<div class="col-md-8">
Expand Down
4 changes: 2 additions & 2 deletions samples/drm/system-priority.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ <h3>DRM system priority example</h3>
multiple DRM systems. In this example, dash.js checks for the support of Widevine before
Playready. </p>
<p>For a detailed explanation on DRM playback in dash.js checkout the
<a href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Digital-Rights-Management-(DRM)-and-license-acquisition"
target="_blank">Wiki</a>.</p>
<a href="https://dashif.org/dash.js/pages/usage/drm.html"
target="_blank">documentation</a>.</p>
</div>
</div>
<div class="col-md-8">
Expand Down
4 changes: 2 additions & 2 deletions samples/drm/system-string-priority.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ <h3>DRM system string priority example</h3>
with the system strings "com.microsoft.playready.recommendation" and
"com.microsoft.playready". </p>
<p>For a detailed explanation on DRM playback in dash.js checkout the
<a href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Digital-Rights-Management-(DRM)-and-license-acquisition"
target="_blank">Wiki</a>.</p>
<a href="https://dashif.org/dash.js/pages/usage/drm.html"
target="_blank">documentation</a>.</p>
</div>
</div>
<div class="col-md-8">
Expand Down
4 changes: 2 additions & 2 deletions samples/drm/widevine.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
<h3>Widevine DRM instantiation example</h3>
<p>This example shows how to use dash.js to play streams with Widevine DRM protection. </p>
<p>For a detailed explanation on DRM playback in dash.js checkout the
<a href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Digital-Rights-Management-(DRM)-and-license-acquisition"
target="_blank">Wiki</a>.</p>
<a href="https://dashif.org/dash.js/pages/usage/drm.html"
target="_blank">documentation</a>.</p>
</div>
</div>
<div class="col-md-8">
Expand Down
2 changes: 1 addition & 1 deletion samples/low-latency/testplayer/testplayer.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<h3><i class="bi bi-info-square"></i> Live low-latency playback</h3>
Example showing how to use dash.js to play low latency streams. The low-latency related parameters
can be adjusted in the settings section. For more information checkout the <a
href="https://github.com/Dash-Industry-Forum/dash.js/wiki/Low-Latency-streaming" target="_blank">Wiki</a>.
href="https://dashif.org/dash.js/pages/usage/low-latency.html" target="_blank">documentation</a>.

<div class="alert alert-warning mt-4" role="alert">
<ul>
Expand Down
4 changes: 2 additions & 2 deletions src/dash/utils/SegmentsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ function getSegment(representation, duration, presentationStartTime, mediaStartT
function isSegmentAvailable(timelineConverter, representation, segment, isDynamic) {
const voPeriod = representation.adaptation.period;

// Avoid requesting segments that overlap the period boundary for periods that are not the last
// Avoid requesting segments for which the start time overlaps the period boundary
if (isFinite(voPeriod.duration) && voPeriod.start + voPeriod.duration <= segment.presentationStartTime) {
return !isDynamic && voPeriod.nextPeriodId === null;
return false
}

if (isDynamic) {
Expand Down
50 changes: 30 additions & 20 deletions src/streaming/StreamProcessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -473,30 +473,40 @@ function StreamProcessor(config) {
// If this statement is true we might be stuck. A static manifest does not change and we did not find a valid request for the target time
// There is no point in trying again. We need to adjust the time in order to find a valid request. This can happen if the user/app seeked into a gap.
// For dynamic manifests this can also happen especially if we jump over the gap in the previous period and are using SegmentTimeline and in case there is a positive eptDelta at the beginning of the period we are stuck.
if (settings.get().streaming.gaps.enableSeekFix && (shouldUseExplicitTimeForRequest || playbackController.getTime() === 0)) {
let adjustedTime;
if (!isDynamic) {
adjustedTime = dashHandler.getValidTimeAheadOfTargetTime(bufferingTime, currentMediaInfo, representation, settings.get().streaming.gaps.threshold);
} else if (isDynamic && representation.segmentInfoType === DashConstants.SEGMENT_TIMELINE) {
// If we find a valid request ahead of the current time then we are in a gap. Segments are only added at the end of the timeline
adjustedTime = dashHandler.getValidTimeAheadOfTargetTime(bufferingTime, currentMediaInfo, representation, settings.get().streaming.gaps.threshold);
}
if (!isNaN(adjustedTime) && adjustedTime !== bufferingTime) {
if (playbackController.isSeeking() || playbackController.getTime() === 0) {
// If we are seeking then playback is stalled. Do a seek to get out of this situation
logger.warn(`Adjusting playback time ${adjustedTime} because of gap in the manifest. Seeking by ${adjustedTime - bufferingTime}`);
playbackController.seek(adjustedTime, false, false);
} else {
// If we are not seeking we should still be playing but we cant find anything to buffer. So we adjust the buffering time and leave the gap jump to the GapController
logger.warn(`Adjusting buffering time ${adjustedTime} because of gap in the manifest. Adjusting time by ${adjustedTime - bufferingTime}`);
setExplicitBufferingTime(adjustedTime)
try {
if (settings.get().streaming.gaps.enableSeekFix && (shouldUseExplicitTimeForRequest || playbackController.getTime() === 0)) {
let adjustedTime;
if (!isDynamic) {
adjustedTime = dashHandler.getValidTimeAheadOfTargetTime(bufferingTime, currentMediaInfo, representation, settings.get().streaming.gaps.threshold);
if (isNaN(adjustedTime)) {
// If there is no valid target time ahead and the buffering time is within the duration of one segment we slightly adjust it
if (bufferingTime >= representation.adaptation.period.mpd.mediaPresentationDuration - representation.segmentDuration) {
adjustedTime = bufferingTime - 0.1;
}
}
} else if (isDynamic && representation.segmentInfoType === DashConstants.SEGMENT_TIMELINE) {
// If we find a valid request ahead of the current time then we are in a gap. Segments are only added at the end of the timeline
adjustedTime = dashHandler.getValidTimeAheadOfTargetTime(bufferingTime, currentMediaInfo, representation, settings.get().streaming.gaps.threshold);
}
if (!isNaN(adjustedTime) && adjustedTime !== bufferingTime) {
if (playbackController.isSeeking() || playbackController.getTime() === 0) {
// If we are seeking then playback is stalled. Do a seek to get out of this situation
logger.warn(`Adjusting playback time ${adjustedTime} because of gap in the manifest. Seeking by ${adjustedTime - bufferingTime}`);
playbackController.seek(adjustedTime, false, false);
} else {
// If we are not seeking we should still be playing but we cant find anything to buffer. So we adjust the buffering time and leave the gap jump to the GapController
logger.warn(`Adjusting buffering time ${adjustedTime} because of gap in the manifest. Adjusting time by ${adjustedTime - bufferingTime}`);
setExplicitBufferingTime(adjustedTime)

if (rescheduleIfNoRequest) {
_noValidRequest();
if (rescheduleIfNoRequest) {
_noValidRequest();
}
}
return;
}
return;
}
} catch (e) {
logger.error(e);
}

// Check if the media is finished. If so, no need to schedule another request
Expand Down
3 changes: 2 additions & 1 deletion src/streaming/controllers/StreamController.js
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,8 @@ function StreamController() {
})

if (!supportedMediaInfos || supportedMediaInfos.length === 0) {
errHandler.error(new DashJSError(Errors.NO_SUPPORTED_KEY_IDS, Errors.NO_SUPPORTED_KEY_IDS_MESSAGE));
const type = streamProcessor.getType();
errHandler.error(new DashJSError(Errors.NO_SUPPORTED_KEY_IDS, `Type: ${type}: ${Errors.NO_SUPPORTED_KEY_IDS_MESSAGE}`));
return
}

Expand Down
36 changes: 25 additions & 11 deletions src/streaming/protection/controllers/ProtectionController.js
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ function ProtectionController(config) {
* @param {object} error
* @private
*/
function _sendLicenseRequestCompleteEvent(data, error) {
function _sendLicenseRequestCompleteEvent(data, error = null) {
eventBus.trigger(events.LICENSE_REQUEST_COMPLETE, { data: data, error: error });
}

Expand Down Expand Up @@ -1127,6 +1127,7 @@ function ProtectionController(config) {
return
}

e.sessionToken.hasTriggeredKeyStatusMapUpdate = true;
const parsedKeyStatuses = e.parsedKeyStatuses;
const ua = Utils.parseUserAgent();
const isEdgeBrowser = ua && ua.browser && ua.browser.name && ua.browser.name.toLowerCase() === 'edge';
Expand Down Expand Up @@ -1161,7 +1162,7 @@ function ProtectionController(config) {

function areKeyIdsUsable(normalizedKeyIds) {
try {
if (!normalizedKeyIds || normalizedKeyIds.size === 0 || !keyStatusMap || keyStatusMap.size === 0 || settings.get().streaming.protection.ignoreKeyStatuses) {
if (!_shouldCheckKeyStatusMap(normalizedKeyIds)) {
return true;
}

Expand All @@ -1177,22 +1178,35 @@ function ProtectionController(config) {

function areKeyIdsExpired(normalizedKeyIds) {
try {
if (!normalizedKeyIds || normalizedKeyIds.size === 0) {
if (!_shouldCheckKeyStatusMap(normalizedKeyIds)) {
return false;
}

let expired = false

normalizedKeyIds.forEach((normalizedKeyId) => {
const keyStatus = keyStatusMap.get(normalizedKeyId)
expired = keyStatus && keyStatus === ProtectionConstants.MEDIA_KEY_STATUSES.EXPIRED
return [...normalizedKeyIds].every((normalizedKeyId) => {
const keyStatus = keyStatusMap.get(normalizedKeyId);
return keyStatus === ProtectionConstants.MEDIA_KEY_STATUSES.EXPIRED;
})

return expired
} catch (error) {
logger.error(error);
return true
return false
}
}

function _shouldCheckKeyStatusMap(normalizedKeyIds) {
const sessionTokens = protectionModel.getSessionTokens();

if (sessionTokens && sessionTokens.length > 0) {
const targetSessionTokens = sessionTokens.filter((sessionToken) => {
return [...normalizedKeyIds].includes(sessionToken.normalizedKeyId);
})
const hasNotTriggeredKeyStatusMapUpdate = targetSessionTokens.some((sessionToken) => {
return !sessionToken.hasTriggeredKeyStatusMapUpdate;
})
if (hasNotTriggeredKeyStatusMapUpdate) {
return false;
}
}
return !settings.get().streaming.protection.ignoreKeyStatuses && normalizedKeyIds && normalizedKeyIds.size > 0 && keyStatusMap && keyStatusMap.size > 0
}

instance = {
Expand Down
3 changes: 3 additions & 0 deletions src/streaming/protection/models/DefaultProtectionModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ function DefaultProtectionModel(config) {

const session = mediaKeys.createSession(keySystemMetadata.sessionType);
const sessionToken = _createSessionToken(session, keySystemMetadata);
sessionToken.hasTriggeredKeyStatusMapUpdate = true;

// Load persisted session data into our newly created session object
session.load(sessionId).then(function (success) {
Expand Down Expand Up @@ -455,9 +456,11 @@ function DefaultProtectionModel(config) {
const token = { // Implements SessionToken
session: session,
keyId: keySystemMetadata.keyId,
normalizedKeyId: keySystemMetadata.keyId.replace(/-/g, '').toLowerCase(),
initData: keySystemMetadata.initData,
sessionId: keySystemMetadata.sessionId,
sessionType: keySystemMetadata.sessionType,
hasTriggeredKeyStatusMapUpdate: false,

// This is our main event handler for all desired MediaKeySession events
// These events are translated into our API-independent versions of the
Expand Down
2 changes: 2 additions & 0 deletions src/streaming/protection/models/ProtectionModel_01b.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ function ProtectionModel_01b(config) {
const newSession = { // Implements SessionToken
sessionId: null,
keyId: ksInfo.keyId,
normalizedKeyId: ksInfo.keyId.replace(/-/g, '').toLowerCase(),
initData: ksInfo.initData,
hasTriggeredKeyStatusMapUpdate: false,

getKeyId: function () {
return this.keyId;
Expand Down
2 changes: 2 additions & 0 deletions src/streaming/protection/models/ProtectionModel_3Feb2014.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,9 @@ function ProtectionModel_3Feb2014(config) {
// Implements SessionToken
session: keySession,
keyId: ksInfo.keyId,
normalizedKeyId: ksInfo.keyId.replace(/-/g, '').toLowerCase(),
initData: ksInfo.initData,
hasTriggeredKeyStatusMapUpdate: false,

getKeyId: function () {
return this.keyId;
Expand Down
28 changes: 28 additions & 0 deletions test/functional/config/test-configurations/streams/drm.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,34 @@
"excludedTestfiles": [
"playback-advanced/preload"
]
},
{
"name": "LiveSim2 - DRM EZDRM-2-keys-cbcs",
"type": "live",
"url": "https://livesim2.dashif.org/livesim2/drm_EZDRM-2-keys-cbcs/testpic_2s/Manifest.mpd",
"includedTestfiles": [
"playback/*",
"drm/keep-media-key-sessions"
],
"excludedPlatforms": [
{
"browser": "safari"
}
]
},
{
"name": "LiveSim2 - DRM EZDRM-1-key-cbcs",
"type": "live",
"url": "https://livesim2.dashif.org/livesim2/drm_EZDRM-1-key-cbcs/testpic_2s/Manifest.mpd",
"includedTestfiles": [
"playback/*",
"drm/keep-media-key-sessions"
],
"excludedPlatforms": [
{
"browser": "safari"
}
]
}
]
}
Loading

0 comments on commit 778b0a3

Please sign in to comment.