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

Feature: UrlQueryInfo and ExtUrlQueryInfo support #4578

Merged
merged 10 commits into from
Oct 30, 2024
194 changes: 194 additions & 0 deletions samples/advanced/ext-url-query-info.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>Flexible Insertion of URL Parameters Sample</title>

<script src="../../dist/dash.all.debug.js"></script>

<!-- Bootstrap core CSS -->
<link href="../lib/bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="../lib/main.css" rel="stylesheet">

<style>
video {
width: 640px;
height: 360px;
}

#trace {
height: 500px;
margin-top: 20px;
font-size: 10px;
overflow-y: auto;
}

#manifestContent {
margin-top: 20px;
font-size: 10px;
white-space: pre-wrap;
word-wrap: break-word;
}
</style>

<script class="code">
var player;

function init() {
var video = document.querySelector('video');
var manifestSelect = document.getElementById('manifestSelect');
var queryParamsInput = document.getElementById('queryParamsInput');
var loadButton = document.getElementById('loadButton');

player = dashjs.MediaPlayer().create();
player.initialize(video, null, false);

player.on(dashjs.MediaPlayer.events.MANIFEST_LOADED, function (event) {
var manifestUrl = getManifestUrlWithQueryParams(manifestSelect.value, queryParamsInput.value);
fetchManifest(manifestUrl);
});

player.on(dashjs.MediaPlayer.events.FRAGMENT_LOADING_COMPLETED, function (event) {
var url = event.request.url;
var formattedUrl = highlightQueryParams(url);
log(formattedUrl);
});

loadButton.addEventListener('click', function () {
updateManifestSource();
});
}

function updateManifestSource() {
var manifestSelect = document.getElementById('manifestSelect');
var queryParamsInput = document.getElementById('queryParamsInput');
var url = getManifestUrlWithQueryParams(manifestSelect.value, queryParamsInput.value);
player.attachSource(url);
clearLog();
clearManifestContent();
}

function getManifestUrlWithQueryParams(url, queryParams) {
if (queryParams) {
var separator = url.includes('?') ? '&' : '?';
return url + separator + encodeURI(queryParams);
}
return url;
}

function highlightQueryParams(url) {
var parts = url.split('?');
if (parts.length > 1) {
var baseUrl = parts[0];
var queryParams = parts[1];
return baseUrl + '?<strong>' + queryParams + '</strong>';
} else {
return url;
}
}

function fetchManifest(url) {
fetch(url)
.then(function (response) {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.text();
})
.then(function (data) {
displayManifestContent(data);
})
.catch(function (error) {
console.error('There has been a problem with your fetch operation:', error);
});
}

function displayManifestContent(content) {
var manifestPanel = document.getElementById('manifestContent');
manifestPanel.textContent = content;
}

function log(msg) {
var tracePanel = document.getElementById('trace');
var logEntry = document.createElement('div');
logEntry.innerHTML = msg;
tracePanel.appendChild(logEntry);
tracePanel.scrollTop = tracePanel.scrollHeight;
console.log(msg);
}

function clearLog() {
var tracePanel = document.getElementById('trace');
tracePanel.innerHTML = '';
}

function clearManifestContent() {
var manifestPanel = document.getElementById('manifestContent');
manifestPanel.textContent = '';
}

document.addEventListener('DOMContentLoaded', function () {
init();
});
</script>
</head>

<body>

<main>
<div class="container py-4">
<header class="pb-3 mb-4 border-bottom">
<img src="../lib/img/dashjs-logo.png" width="200">
</header>
<div class="row">
<div class="col-md-12">
<div class="h-100 p-5 bg-light border rounded-3">
<h3>Flexible Insertion of URL Parameters Sample</h3>
<p>This sample demonstrates the <strong>Flexible Insertion of URL Parameters</strong> in
dash.js.</p>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-md-6">
<label for="manifestSelect">Manifest:</label>
<input id="manifestSelect" type="text" class="form-control">
<label for="queryParamsInput" class="mt-2">Add Query Parameters to Manifest Request:</label>
<input id="queryParamsInput" type="text" class="form-control" value="token=1234">
<button id="loadButton" class="btn btn-primary mt-2">Load</button>
<video controls="true" class="mt-3"></video>
</div>
<div class="col-md-6">
<div class="form-floating">
<div class="form-control" id="trace"></div>
<label for="trace">Requests Made by Player</label>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-md-12">
<h5>Manifest Content:</h5>
<pre id="manifestContent" class="border p-3"></pre>
</div>
</div>
<div class="row mt-2">
<div class="col-md-12">
<div id="code-output"></div>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
&copy; DASH-IF
</footer>
</div>
</main>

<script>
document.addEventListener('DOMContentLoaded', function () {
init();
});
</script>
<script src="../highlighter.js"></script>
</body>

</html>
11 changes: 11 additions & 0 deletions samples/samples.json
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,17 @@
"Audio"
]
},
{
"title": "Flexible Insertion of URL Parameters Sample",
"description": "This sample demonstrates the Flexible Insertion of URL Parameters in dash.js.",
"href": "advanced/ext-url-query-info.html",
"image": "lib/img/bbb-1.jpg",
"labels": [
"VoD",
"Video",
"Audio"
]
},
{
"title": "Custom Capabilities Filters",
"description": "This sample shows how to filter representations.",
Expand Down
4 changes: 4 additions & 0 deletions src/core/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ import Events from './events/Events.js';
* supportedEssentialProperties: [
* { schemeIdUri: Constants.FONT_DOWNLOAD_DVB_SCHEME },
* { schemeIdUri: Constants.COLOUR_PRIMARIES_SCHEME_ID_URI, value: /1|5|6|7/ },
* { schemeIdUri: Constants.URL_QUERY_INFO_SCHEME },
* { schemeIdUri: Constants.EXT_URL_QUERY_INFO_SCHEME },
* { schemeIdUri: Constants.MATRIX_COEFFICIENTS_SCHEME_ID_URI, value: /0|1|5|6/ },
* { schemeIdUri: Constants.TRANSFER_CHARACTERISTICS_SCHEME_ID_URI, value: /1|6|13|14|15/ },
* ...Constants.THUMBNAILS_SCHEME_ID_URIS.map(ep => { return { 'schemeIdUri': ep }; })
Expand Down Expand Up @@ -1058,6 +1060,8 @@ function Settings() {
supportedEssentialProperties: [
{ schemeIdUri: Constants.FONT_DOWNLOAD_DVB_SCHEME },
{ schemeIdUri: Constants.COLOUR_PRIMARIES_SCHEME_ID_URI, value: /1|5|6|7/ },
{ schemeIdUri: Constants.URL_QUERY_INFO_SCHEME },
{ schemeIdUri: Constants.EXT_URL_QUERY_INFO_SCHEME },
{ schemeIdUri: Constants.MATRIX_COEFFICIENTS_SCHEME_ID_URI, value: /0|1|5|6/ },
{ schemeIdUri: Constants.TRANSFER_CHARACTERISTICS_SCHEME_ID_URI, value: /1|6|13|14|15/ },
...Constants.THUMBNAILS_SCHEME_ID_URIS.map(ep => { return { 'schemeIdUri': ep }; })
Expand Down
15 changes: 15 additions & 0 deletions src/core/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ class Utils {
return headers;
}

/**
* Parses query parameters from a string and returns them as an array of key-value pairs.
* @param {string} queryParamString - A string containing the query parameters.
* @return {Array<{key: string, value: string}>} An array of objects representing the query parameters.
*/
static parseQueryParams(queryParamString) {
const params = [];
const url = new URL('http://dummyurl.com?' + queryParamString);
const searchParams = new URLSearchParams(url.search);
for (const [key, value] of searchParams.entries()) {
params.push({ key: decodeURIComponent(key), value: decodeURIComponent(value) });
}
return params;
}

static generateUuid() {
let dt = new Date().getTime();
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
Expand Down
5 changes: 5 additions & 0 deletions src/dash/constants/DashConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ export default {
MIN_BUFFER_TIME: 'minBufferTime',
MP4_PROTECTION_SCHEME: 'urn:mpeg:dash:mp4protection:2011',
MPD: 'MPD',
MPD_TYPE: 'mpd',
MPD_PATCH_TYPE: 'mpdpatch',
ORIGINAL_MPD_ID: 'mpdId',
ORIGINAL_PUBLISH_TIME: 'originalPublishTime',
PATCH_LOCATION: 'PatchLocation',
Expand All @@ -138,6 +140,7 @@ export default {
PUBLISH_TIME: 'publishTime',
QUALITY_RANKING : 'qualityRanking',
QUERY_BEFORE_START: 'queryBeforeStart',
QUERY_PART: '$querypart$',
RANGE: 'range',
RATING: 'Rating',
REF: 'ref',
Expand All @@ -158,6 +161,7 @@ export default {
SEGMENT_PROFILES: 'segmentProfiles',
SEGMENT_TEMPLATE: 'SegmentTemplate',
SEGMENT_TIMELINE: 'SegmentTimeline',
SEGMENT_TYPE: 'segment',
SEGMENT_URL: 'SegmentURL',
SERVICE_DESCRIPTION: 'ServiceDescription',
SERVICE_DESCRIPTION_LATENCY: 'Latency',
Expand All @@ -172,6 +176,7 @@ export default {
START_NUMBER: 'startNumber',
START_WITH_SAP: 'startWithSAP',
STATIC: 'static',
STEERING_TYPE: 'steering',
SUBSET: 'Subset',
SUBTITLE: 'subtitle',
SUB_REPRESENTATION: 'SubRepresentation',
Expand Down
2 changes: 2 additions & 0 deletions src/streaming/constants/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ export default {
THUMBNAILS_SCHEME_ID_URIS: ['http://dashif.org/thumbnail_tile', 'http://dashif.org/guidelines/thumbnail_tile'],
FONT_DOWNLOAD_DVB_SCHEME: 'urn:dvb:dash:fontdownload:2014',
COLOUR_PRIMARIES_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:ColourPrimaries',
URL_QUERY_INFO_SCHEME: 'urn:mpeg:dash:urlparam:2014',
EXT_URL_QUERY_INFO_SCHEME: 'urn:mpeg:dash:urlparam:2016',
MATRIX_COEFFICIENTS_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:MatrixCoefficients',
TRANSFER_CHARACTERISTICS_SCHEME_ID_URI: 'urn:mpeg:mpegB:cicp:TransferCharacteristics',
HDR_METADATA_FORMAT_SCHEME_ID_URI: 'urn:dvb:dash:hdr-dmi',
Expand Down
Loading